1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
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 Copy image tests for GL_EXT_copy_image.
22 *//*--------------------------------------------------------------------*/
23
24#include "es31fCopyImageTests.hpp"
25
26#include "tes31TestCase.hpp"
27
28#include "glsTextureTestUtil.hpp"
29
30#include "gluContextInfo.hpp"
31#include "gluObjectWrapper.hpp"
32#include "gluRenderContext.hpp"
33#include "gluStrUtil.hpp"
34#include "gluTextureUtil.hpp"
35#include "gluPixelTransfer.hpp"
36
37#include "glwEnums.hpp"
38#include "glwFunctions.hpp"
39
40#include "tcuCompressedTexture.hpp"
41#include "tcuFloat.hpp"
42#include "tcuImageCompare.hpp"
43#include "tcuTestLog.hpp"
44#include "tcuTexture.hpp"
45#include "tcuTextureUtil.hpp"
46#include "tcuVector.hpp"
47#include "tcuVectorUtil.hpp"
48#include "tcuSeedBuilder.hpp"
49#include "tcuResultCollector.hpp"
50
51#include "deArrayBuffer.hpp"
52#include "deFloat16.h"
53#include "deRandom.hpp"
54#include "deStringUtil.hpp"
55#include "deUniquePtr.hpp"
56#include "deArrayUtil.hpp"
57
58#include <map>
59#include <string>
60#include <vector>
61
62using namespace deqp::gls::TextureTestUtil;
63using namespace glu::TextureTestUtil;
64
65using tcu::Float;
66using tcu::IVec2;
67using tcu::IVec3;
68using tcu::IVec4;
69using tcu::Sampler;
70using tcu::ScopedLogSection;
71using tcu::TestLog;
72using tcu::Vec4;
73using tcu::SeedBuilder;
74
75using de::ArrayBuffer;
76
77using std::map;
78using std::string;
79using std::vector;
80using std::pair;
81
82namespace deqp
83{
84namespace gles31
85{
86namespace Functional
87{
88namespace
89{
90
91enum ViewClass
92{
93	VIEWCLASS_128_BITS = 0,
94	VIEWCLASS_96_BITS,
95	VIEWCLASS_64_BITS,
96	VIEWCLASS_48_BITS,
97	VIEWCLASS_32_BITS,
98	VIEWCLASS_24_BITS,
99	VIEWCLASS_16_BITS,
100	VIEWCLASS_8_BITS,
101
102	VIEWCLASS_EAC_R11,
103	VIEWCLASS_EAC_RG11,
104	VIEWCLASS_ETC2_RGB,
105	VIEWCLASS_ETC2_RGBA,
106	VIEWCLASS_ETC2_EAC_RGBA,
107	VIEWCLASS_ASTC_4x4_RGBA,
108	VIEWCLASS_ASTC_5x4_RGBA,
109	VIEWCLASS_ASTC_5x5_RGBA,
110	VIEWCLASS_ASTC_6x5_RGBA,
111	VIEWCLASS_ASTC_6x6_RGBA,
112	VIEWCLASS_ASTC_8x5_RGBA,
113	VIEWCLASS_ASTC_8x6_RGBA,
114	VIEWCLASS_ASTC_8x8_RGBA,
115	VIEWCLASS_ASTC_10x5_RGBA,
116	VIEWCLASS_ASTC_10x6_RGBA,
117	VIEWCLASS_ASTC_10x8_RGBA,
118	VIEWCLASS_ASTC_10x10_RGBA,
119	VIEWCLASS_ASTC_12x10_RGBA,
120	VIEWCLASS_ASTC_12x12_RGBA
121};
122
123enum Verify
124{
125	VERIFY_NONE = 0,
126	VERIFY_COMPARE_REFERENCE
127};
128
129const char* viewClassToName (ViewClass viewClass)
130{
131	switch (viewClass)
132	{
133		case VIEWCLASS_128_BITS:			return "viewclass_128_bits";
134		case VIEWCLASS_96_BITS:				return "viewclass_96_bits";
135		case VIEWCLASS_64_BITS:				return "viewclass_64_bits";
136		case VIEWCLASS_48_BITS:				return "viewclass_48_bits";
137		case VIEWCLASS_32_BITS:				return "viewclass_32_bits";
138		case VIEWCLASS_24_BITS:				return "viewclass_24_bits";
139		case VIEWCLASS_16_BITS:				return "viewclass_16_bits";
140		case VIEWCLASS_8_BITS:				return "viewclass_8_bits";
141		case VIEWCLASS_EAC_R11:				return "viewclass_eac_r11";
142		case VIEWCLASS_EAC_RG11:			return "viewclass_eac_rg11";
143		case VIEWCLASS_ETC2_RGB:			return "viewclass_etc2_rgb";
144		case VIEWCLASS_ETC2_RGBA:			return "viewclass_etc2_rgba";
145		case VIEWCLASS_ETC2_EAC_RGBA:		return "viewclass_etc2_eac_rgba";
146		case VIEWCLASS_ASTC_4x4_RGBA:		return "viewclass_astc_4x4_rgba";
147		case VIEWCLASS_ASTC_5x4_RGBA:		return "viewclass_astc_5x4_rgba";
148		case VIEWCLASS_ASTC_5x5_RGBA:		return "viewclass_astc_5x5_rgba";
149		case VIEWCLASS_ASTC_6x5_RGBA:		return "viewclass_astc_6x5_rgba";
150		case VIEWCLASS_ASTC_6x6_RGBA:		return "viewclass_astc_6x6_rgba";
151		case VIEWCLASS_ASTC_8x5_RGBA:		return "viewclass_astc_8x5_rgba";
152		case VIEWCLASS_ASTC_8x6_RGBA:		return "viewclass_astc_8x6_rgba";
153		case VIEWCLASS_ASTC_8x8_RGBA:		return "viewclass_astc_8x8_rgba";
154		case VIEWCLASS_ASTC_10x5_RGBA:		return "viewclass_astc_10x5_rgba";
155		case VIEWCLASS_ASTC_10x6_RGBA:		return "viewclass_astc_10x6_rgba";
156		case VIEWCLASS_ASTC_10x8_RGBA:		return "viewclass_astc_10x8_rgba";
157		case VIEWCLASS_ASTC_10x10_RGBA:		return "viewclass_astc_10x10_rgba";
158		case VIEWCLASS_ASTC_12x10_RGBA:		return "viewclass_astc_12x10_rgba";
159		case VIEWCLASS_ASTC_12x12_RGBA:		return "viewclass_astc_12x12_rgba";
160
161		default:
162			DE_ASSERT(false);
163			return NULL;
164	}
165}
166
167const char* targetToName (deUint32 target)
168{
169	switch (target)
170	{
171		case GL_RENDERBUFFER:		return "renderbuffer";
172		case GL_TEXTURE_2D:			return "texture2d";
173		case GL_TEXTURE_3D:			return "texture3d";
174		case GL_TEXTURE_2D_ARRAY:	return "texture2d_array";
175		case GL_TEXTURE_CUBE_MAP:	return "cubemap";
176
177		default:
178			DE_ASSERT(false);
179			return NULL;
180	}
181}
182
183string formatToName (deUint32 format)
184{
185	string enumName;
186
187	if (glu::isCompressedFormat(format))
188		enumName = glu::getCompressedTextureFormatStr(format).toString().substr(14); // Strip GL_COMPRESSED_
189	else
190		enumName = glu::getUncompressedTextureFormatStr(format).toString().substr(3); // Strip GL_
191
192	return de::toLower(enumName);
193}
194
195bool isFloatFormat (deUint32 format)
196{
197	if (glu::isCompressedFormat(format))
198		return false;
199	else
200		return tcu::getTextureChannelClass(glu::mapGLInternalFormat(format).type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
201}
202
203bool isUintFormat (deUint32 format)
204{
205	if (glu::isCompressedFormat(format))
206		return false;
207	else
208		return tcu::getTextureChannelClass(glu::mapGLInternalFormat(format).type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
209}
210
211bool isIntFormat (deUint32 format)
212{
213	if (glu::isCompressedFormat(format))
214		return false;
215	else
216		return tcu::getTextureChannelClass(glu::mapGLInternalFormat(format).type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER;
217}
218
219bool isFixedPointFormat (deUint32 format)
220{
221	if (glu::isCompressedFormat(format))
222		return false;
223	else
224	{
225		const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(glu::mapGLInternalFormat(format).type);
226
227		return channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
228	}
229}
230
231bool isTextureTarget (deUint32 target)
232{
233	return target != GL_RENDERBUFFER;
234}
235
236int getTargetTexDims (deUint32 target)
237{
238	DE_ASSERT(isTextureTarget(target));
239
240	switch (target)
241	{
242		case GL_TEXTURE_1D:
243			return 1;
244
245		case GL_TEXTURE_1D_ARRAY:
246		case GL_TEXTURE_2D:
247		case GL_TEXTURE_CUBE_MAP:
248			return 2;
249
250		case GL_TEXTURE_2D_ARRAY:
251		case GL_TEXTURE_3D:
252			return 3;
253
254		default:
255			DE_ASSERT(false);
256			return -1;
257	}
258}
259
260class RandomizedRenderGrid
261{
262public:
263					RandomizedRenderGrid	(const IVec2& targetSize, const IVec2& cellSize, int maxCellCount, deUint32 seed);
264	bool			nextCell				(void);
265	IVec2			getOrigin				(void) const;
266
267	const IVec2&	getCellSize				(void) const { return m_cellSize; };
268	IVec4			getUsedAreaBoundingBox	(void) const;
269	int				getCellCount			(void) const { return m_cellCount; };
270
271private:
272	static IVec2	getRandomOffset			(deUint32 seed, IVec2 targetSize, IVec2 cellSize, IVec2 grid, int cellCount);
273
274	const IVec2		m_targetSize;
275	const IVec2		m_cellSize;
276	const IVec2		m_grid;
277	int				m_currentCell;
278	const int		m_cellCount;
279	const IVec2		m_baseRandomOffset;
280};
281
282RandomizedRenderGrid::RandomizedRenderGrid (const IVec2& targetSize, const IVec2& cellSize, int maxCellCount, deUint32 seed)
283	: m_targetSize			(targetSize)
284	, m_cellSize			(cellSize)
285	, m_grid				(targetSize / cellSize)
286	, m_currentCell			(0)
287	// If the grid exactly fits height, take one row for randomization.
288	, m_cellCount			(deMin32(maxCellCount, ((targetSize.y() % cellSize.y()) == 0) && m_grid.y() > 1 ? m_grid.x() * (m_grid.y() - 1) :  m_grid.x() * m_grid.y()))
289	, m_baseRandomOffset	(getRandomOffset(seed, targetSize, cellSize, m_grid, m_cellCount))
290{
291}
292
293IVec2 RandomizedRenderGrid::getRandomOffset (deUint32 seed, IVec2 targetSize, IVec2 cellSize, IVec2 grid, int cellCount)
294{
295	de::Random	rng			(seed);
296	IVec2		result;
297	IVec2		extraSpace = targetSize - (cellSize * grid);
298
299	// If there'll be unused rows, donate them into extra space.
300	// (Round the required rows to full cell row to find out how many rows are unused, multiply by size)
301	DE_ASSERT(deDivRoundUp32(cellCount, grid.x()) <= grid.y());
302	extraSpace.y() += (grid.y() - deDivRoundUp32(cellCount, grid.x())) * cellSize.y();
303
304	DE_ASSERT(targetSize.x() > cellSize.x() && targetSize.y() > cellSize.y());
305	// If grid fits perfectly just one row of cells, just give up on randomizing.
306	DE_ASSERT(extraSpace.x() > 0 || extraSpace.y() > 0 || grid.y() == 1);
307	DE_ASSERT(extraSpace.x() + grid.x() * cellSize.x() == targetSize.x());
308
309	// \note Putting these as ctor params would make evaluation order undefined, I think <sigh>. Hence,
310	// no direct return.
311	result.x() = rng.getInt(0, extraSpace.x());
312	result.y() = rng.getInt(0, extraSpace.y());
313	return result;
314}
315
316bool RandomizedRenderGrid::nextCell (void)
317{
318	if (m_currentCell >= getCellCount())
319		return false;
320
321	m_currentCell++;
322	return true;
323}
324
325IVec2 RandomizedRenderGrid::getOrigin (void) const
326{
327	const int	gridX		  = (m_currentCell - 1) % m_grid.x();
328	const int	gridY		  = (m_currentCell - 1) / m_grid.x();
329	const IVec2 currentOrigin = (IVec2(gridX, gridY) * m_cellSize) + m_baseRandomOffset;
330
331	DE_ASSERT(currentOrigin.x() >= 0 && (currentOrigin.x() + m_cellSize.x()) <= m_targetSize.x());
332	DE_ASSERT(currentOrigin.y() >= 0 && (currentOrigin.y() + m_cellSize.y()) <= m_targetSize.y());
333
334	return currentOrigin;
335}
336
337IVec4 RandomizedRenderGrid::getUsedAreaBoundingBox (void) const
338{
339	const IVec2 lastCell	(de::min(m_currentCell + 1, m_grid.x()), ((m_currentCell + m_grid.x() - 1) / m_grid.x()));
340	const IVec2 size		= lastCell * m_cellSize;
341
342	return IVec4(m_baseRandomOffset.x(), m_baseRandomOffset.y(), size.x(), size.y());
343}
344
345class ImageInfo
346{
347public:
348					ImageInfo		(deUint32 format, deUint32 target, const IVec3& size);
349
350	deUint32		getFormat		(void) const { return m_format; }
351	deUint32		getTarget		(void) const { return m_target; }
352	const IVec3&	getSize			(void) const { return m_size; }
353
354private:
355	deUint32		m_format;
356	deUint32		m_target;
357	IVec3			m_size;
358};
359
360ImageInfo::ImageInfo (deUint32 format, deUint32 target, const IVec3& size)
361	: m_format		(format)
362	, m_target		(target)
363	, m_size		(size)
364{
365	DE_ASSERT(m_target == GL_TEXTURE_2D_ARRAY || m_target == GL_TEXTURE_3D || m_size.z() == 1);
366	DE_ASSERT(isTextureTarget(m_target) || !glu::isCompressedFormat(m_target));
367}
368
369
370SeedBuilder& operator<< (SeedBuilder& builder, const ImageInfo& info)
371{
372	builder << info.getFormat() << info.getTarget() << info.getSize();
373	return builder;
374}
375
376const glu::ObjectTraits& getObjectTraits (const ImageInfo& info)
377{
378	if (isTextureTarget(info.getTarget()))
379		return glu::objectTraits(glu::OBJECTTYPE_TEXTURE);
380	else
381		return glu::objectTraits(glu::OBJECTTYPE_RENDERBUFFER);
382}
383
384int getLevelCount (const ImageInfo& info)
385{
386	const deUint32	target	= info.getTarget();
387	const IVec3		size	= info.getSize();
388
389	if (target == GL_RENDERBUFFER)
390		return 1;
391	else if (target == GL_TEXTURE_2D_ARRAY)
392	{
393		const int maxSize = de::max(size.x(), size.y());
394
395		return deLog2Ceil32(maxSize);
396	}
397	else
398	{
399		const int maxSize = de::max(size.x(), de::max(size.y(), size.z()));
400
401		return deLog2Ceil32(maxSize);
402	}
403}
404
405IVec3 getLevelSize (deUint32 target, const IVec3& baseSize, int level)
406{
407	IVec3 size;
408
409	if (target != GL_TEXTURE_2D_ARRAY)
410	{
411		for (int i = 0; i < 3; i++)
412			size[i] = de::max(baseSize[i] >> level, 1);
413	}
414	else
415	{
416		for (int i = 0; i < 2; i++)
417			size[i] = de::max(baseSize[i] >> level, 1);
418
419		size[2] = baseSize[2];
420	}
421
422	return size;
423}
424
425deUint32 mapFaceNdxToFace (int ndx)
426{
427	const deUint32 cubeFaces[] =
428	{
429		GL_TEXTURE_CUBE_MAP_POSITIVE_X,
430		GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
431
432		GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
433		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
434
435		GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
436		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
437	};
438
439	return de::getSizedArrayElement<6>(cubeFaces, ndx);
440}
441
442// Class for iterating over mip levels and faces/slices/... of a texture.
443class TextureImageIterator
444{
445public:
446						TextureImageIterator	(const ImageInfo info, int levelCount);
447						~TextureImageIterator	(void)							{}
448
449	// Need to call next image once, newly constructed not readable, except for getSize
450	bool				nextImage				(void);
451	bool				hasNextImage			(void) const					{ return (m_currentLevel < (m_levelCount - 1)) || m_currentImage < (m_levelImageCount - 1); }
452
453	int					getMipLevel				(void) const					{ return m_currentLevel; }
454	int					getMipLevelCount		(void) const					{ return m_levelCount; }
455	int					getCurrentImage			(void) const					{ return m_currentImage;}
456	int					getLevelImageCount		(void) const					{ return m_levelImageCount; }
457	IVec2				getSize					(void) const					{ return m_levelSize.toWidth<2>(); }	// Assume that image sizes never grow over iteration
458	deUint32			getTarget				(void) const					{ return m_info.getTarget(); }
459
460private:
461	int					m_levelImageCount;		// Need to be defined in CTOR for the hasNextImage to work!
462	const ImageInfo		m_info;
463	int					m_currentLevel;
464	IVec3				m_levelSize;
465	int					m_currentImage;
466	const int			m_levelCount;
467};
468
469TextureImageIterator::TextureImageIterator (const ImageInfo info, int levelCount)
470	: m_levelImageCount	(info.getTarget() == GL_TEXTURE_CUBE_MAP ? 6 : getLevelSize(info.getTarget(), info.getSize(), 0).z())
471	, m_info			(info)
472	, m_currentLevel	(0)
473	, m_levelSize		(getLevelSize(info.getTarget(), info.getSize(), 0))
474	, m_currentImage	(-1)
475	, m_levelCount		(levelCount)
476{
477	DE_ASSERT(m_levelCount <= getLevelCount(info));
478}
479
480bool TextureImageIterator::nextImage (void)
481{
482	if (!hasNextImage())
483		return false;
484
485	m_currentImage++;
486	if (m_currentImage == m_levelImageCount)
487	{
488		m_currentLevel++;
489		m_currentImage		= 0;
490
491		m_levelSize			= getLevelSize(m_info.getTarget(), m_info.getSize(), m_currentLevel);
492
493		if (getTarget() == GL_TEXTURE_CUBE_MAP)
494			m_levelImageCount = 6;
495		else
496			m_levelImageCount = m_levelSize.z();
497	}
498	DE_ASSERT(m_currentLevel < m_levelCount);
499	DE_ASSERT(m_currentImage < m_levelImageCount);
500	return true;
501}
502
503// Get name
504string getTextureImageName (int textureTarget, int mipLevel, int imageIndex)
505{
506	std::ostringstream result;
507	result << "Level";
508	result << mipLevel;
509	switch (textureTarget)
510	{
511		case GL_TEXTURE_2D:			break;
512		case GL_TEXTURE_3D:			result << "Slice" << imageIndex; break;
513		case GL_TEXTURE_CUBE_MAP:	result << "Face" << imageIndex; break;
514		case GL_TEXTURE_2D_ARRAY:	result << "Layer" << imageIndex; break;
515		default:
516			DE_FATAL("Unsupported texture target");
517			break;
518	}
519	return result.str();
520}
521
522// Get description
523string getTextureImageDescription (int textureTarget, int mipLevel, int imageIndex)
524{
525	std::ostringstream result;
526	result << "level ";
527	result << mipLevel;
528
529	switch (textureTarget)
530	{
531		case GL_TEXTURE_2D:			break;
532		case GL_TEXTURE_3D:			result << " and Slice " << imageIndex; break;
533		case GL_TEXTURE_CUBE_MAP:	result << " and Face " << imageIndex; break;
534		case GL_TEXTURE_2D_ARRAY:	result << " and Layer " << imageIndex; break;
535		default:
536			DE_FATAL("Unsupported texture target");
537			break;
538	}
539	return result.str();
540}
541
542// Compute texture coordinates
543void computeQuadTexCoords(vector<float>& texCoord, const TextureImageIterator& iteration)
544{
545	const int currentImage = iteration.getCurrentImage();
546	switch (iteration.getTarget())
547	{
548		case GL_TEXTURE_2D:
549			computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
550			break;
551
552		case GL_TEXTURE_3D:
553		{
554			const float r = (float(currentImage) + 0.5f) / (float)iteration.getLevelImageCount();
555			computeQuadTexCoord3D(texCoord, tcu::Vec3(0.0f, 0.0f, r), tcu::Vec3(1.0f, 1.0f, r), tcu::IVec3(0, 1, 2));
556			break;
557		}
558
559		case GL_TEXTURE_CUBE_MAP:
560			computeQuadTexCoordCube(texCoord, glu::getCubeFaceFromGL(mapFaceNdxToFace(currentImage)));
561			break;
562
563		case GL_TEXTURE_2D_ARRAY:
564			computeQuadTexCoord2DArray(texCoord, currentImage, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
565			break;
566
567		default:
568			DE_FATAL("Unsupported texture target");
569	}
570}
571
572// Struct for storing each reference image with necessary metadata.
573struct CellContents
574{
575	IVec2			origin;
576	tcu::Surface	reference;
577	std::string		name;
578	std::string		description;
579};
580
581// Return format that has more restrictions on texel data.
582deUint32 getMoreRestrictiveFormat (deUint32 formatA, deUint32 formatB)
583{
584	if (formatA == formatB)
585		return formatA;
586	else if (glu::isCompressedFormat(formatA) && isAstcFormat(glu::mapGLCompressedTexFormat(formatA)))
587		return formatA;
588	else if (glu::isCompressedFormat(formatB) && isAstcFormat(glu::mapGLCompressedTexFormat(formatB)))
589		return formatB;
590	else if (isFloatFormat(formatA))
591	{
592		DE_ASSERT(!isFloatFormat(formatB));
593
594		return formatA;
595	}
596	else if (isFloatFormat(formatB))
597	{
598		DE_ASSERT(!isFloatFormat(formatA));
599
600		return formatB;
601	}
602	else if (glu::isCompressedFormat(formatA))
603	{
604		return formatA;
605	}
606	else if (glu::isCompressedFormat(formatB))
607	{
608		return formatB;
609	}
610	else
611		return formatA;
612}
613
614int getTexelBlockSize (deUint32 format)
615{
616	if (glu::isCompressedFormat(format))
617		return tcu::getBlockSize(glu::mapGLCompressedTexFormat(format));
618	else
619		return glu::mapGLInternalFormat(format).getPixelSize();
620}
621
622IVec3 getTexelBlockPixelSize (deUint32 format)
623{
624	if (glu::isCompressedFormat(format))
625		return tcu::getBlockPixelSize(glu::mapGLCompressedTexFormat(format));
626	else
627		return IVec3(1, 1, 1);
628}
629
630bool isColorRenderable (deUint32 format)
631{
632	switch (format)
633	{
634		case GL_R8:
635		case GL_RG8:
636		case GL_RGB8:
637		case GL_RGB565:
638		case GL_RGB4:
639		case GL_RGB5_A1:
640		case GL_RGBA8:
641		case GL_RGB10_A2:
642		case GL_RGB10_A2UI:
643		case GL_SRGB8_ALPHA8:
644		case GL_R8I:
645		case GL_R8UI:
646		case GL_R16I:
647		case GL_R16UI:
648		case GL_R32I:
649		case GL_R32UI:
650		case GL_RG8I:
651		case GL_RG8UI:
652		case GL_RG16I:
653		case GL_RG16UI:
654		case GL_RG32I:
655		case GL_RG32UI:
656		case GL_RGBA8I:
657		case GL_RGBA8UI:
658		case GL_RGBA16I:
659		case GL_RGBA16UI:
660		case GL_RGBA32I:
661		case GL_RGBA32UI:
662			return true;
663
664		default:
665			return false;
666	}
667}
668
669deUint32 getTypeForInternalFormat (deUint32 format)
670{
671	return glu::getTransferFormat(glu::mapGLInternalFormat(format)).dataType;
672}
673
674void genTexel (de::Random& rng, deUint32 glFormat, int texelBlockSize, const int texelCount, deUint8* buffer)
675{
676	if (isFloatFormat(glFormat))
677	{
678		const tcu::TextureFormat		format	= glu::mapGLInternalFormat(glFormat);
679		const tcu::PixelBufferAccess	access	(format, texelCount, 1, 1, buffer);
680		const tcu::TextureFormatInfo	info	= tcu::getTextureFormatInfo(format);
681
682		for (int texelNdx = 0; texelNdx < texelCount; texelNdx++)
683		{
684			const float	red		= rng.getFloat(info.valueMin.x(), info.valueMax.x());
685			const float green	= rng.getFloat(info.valueMin.y(), info.valueMax.y());
686			const float blue	= rng.getFloat(info.valueMin.z(), info.valueMax.z());
687			const float alpha	= rng.getFloat(info.valueMin.w(), info.valueMax.w());
688
689			const Vec4	color	(red, green, blue, alpha);
690
691			access.setPixel(color, texelNdx, 0, 0);
692		}
693	}
694	else if (glu::isCompressedFormat(glFormat))
695	{
696		const tcu::CompressedTexFormat compressedFormat = glu::mapGLCompressedTexFormat(glFormat);
697
698		if (tcu::isAstcFormat(compressedFormat))
699		{
700			const int		BLOCK_SIZE				= 16;
701			const deUint8	blocks[][BLOCK_SIZE]	=
702			{
703				// \note All of the following blocks are valid in LDR mode.
704				{ 252,	253,	255,	255,	255,	255,	255,	255,	8,		71,		90,		78,		22,		17,		26,		66,		},
705				{ 252,	253,	255,	255,	255,	255,	255,	255,	220,	74,		139,	235,	249,	6,		145,	125		},
706				{ 252,	253,	255,	255,	255,	255,	255,	255,	223,	251,	28,		206,	54,		251,	160,	174		},
707				{ 252,	253,	255,	255,	255,	255,	255,	255,	39,		4,		153,	219,	180,	61,		51,		37		},
708				{ 67,	2,		0,		254,	1,		0,		64,		215,	83,		211,	159,	105,	41,		140,	50,		2		},
709				{ 67,	130,	0,		170,	84,		255,	65,		215,	83,		211,	159,	105,	41,		140,	50,		2		},
710				{ 67,	2,		129,	38,		51,		229,	95,		215,	83,		211,	159,	105,	41,		140,	50,		2		},
711				{ 67,	130,	193,	56,		213,	144,	95,		215,	83,		211,	159,	105,	41,		140,	50,		2		}
712			};
713
714			DE_ASSERT(texelBlockSize == BLOCK_SIZE);
715
716			for (int i = 0; i < texelCount; i++)
717			{
718				const int blockNdx = rng.getInt(0, DE_LENGTH_OF_ARRAY(blocks)-1);
719
720				deMemcpy(buffer + i * BLOCK_SIZE,  blocks[blockNdx], BLOCK_SIZE);
721			}
722		}
723		else
724		{
725			for (int i = 0; i < texelBlockSize * texelCount; i++)
726			{
727				const deUint8 val = rng.getUint8();
728
729				buffer[i] = val;
730			}
731		}
732	}
733	else
734	{
735		for (int i = 0; i < texelBlockSize * texelCount; i++)
736		{
737			const deUint8 val = rng.getUint8();
738
739			buffer[i] = val;
740		}
741	}
742}
743
744IVec3 divRoundUp (const IVec3& a, const IVec3& b)
745{
746	IVec3 res;
747
748	for (int i =0; i < 3; i++)
749		res[i] = a[i] / b[i] + ((a[i] % b[i]) ? 1 : 0);
750
751	return res;
752}
753
754deUint32 getFormatForInternalFormat (deUint32 format)
755{
756	return glu::getTransferFormat(glu::mapGLInternalFormat(format)).format;
757}
758
759void genericTexImage (const glw::Functions&	gl,
760					  deUint32				target,
761					  int					faceNdx,
762					  int					level,
763					  const IVec3&			size,
764					  deUint32				format,
765					  size_t				dataSize,
766					  const void*			data)
767{
768	const deUint32 glTarget = (target == GL_TEXTURE_CUBE_MAP ? mapFaceNdxToFace(faceNdx) : target);
769
770	DE_ASSERT(target == GL_TEXTURE_CUBE_MAP || faceNdx == 0);
771
772	if (glu::isCompressedFormat(format))
773	{
774		switch (getTargetTexDims(target))
775		{
776			case 2:
777				DE_ASSERT(size.z() == 1);
778				gl.compressedTexImage2D(glTarget, level, format, (glw::GLsizei)size.x(), (glw::GLsizei)size.y(), 0, (glw::GLsizei)dataSize, data);
779				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage2D failed.");
780				break;
781
782			case 3:
783				gl.compressedTexImage3D(glTarget, level, format, (glw::GLsizei)size.x(), (glw::GLsizei)size.y(), (glw::GLsizei)size.z(), 0, (glw::GLsizei)dataSize, data);
784				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexImage3D failed.");
785				break;
786
787			default:
788				DE_ASSERT(false);
789		}
790	}
791	else
792	{
793		const deUint32	glFormat	= getFormatForInternalFormat(format);
794		const deUint32	glType		= getTypeForInternalFormat(format);
795
796		switch (getTargetTexDims(target))
797		{
798			case 2:
799				DE_ASSERT(size.z() == 1);
800				gl.texImage2D(glTarget, level, format, (glw::GLsizei)size.x(), (glw::GLsizei)size.y(), 0, glFormat, glType, data);
801				GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D failed.");
802				break;
803
804			case 3:
805				gl.texImage3D(glTarget, level, format, (glw::GLsizei)size.x(), (glw::GLsizei)size.y(), (glw::GLsizei)size.z(), 0, glFormat, glType, data);
806				GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage3D failed.");
807				break;
808
809			default:
810				DE_ASSERT(false);
811		}
812	}
813}
814
815void genTextureImage (const glw::Functions&				gl,
816					  de::Random&						rng,
817					  deUint32							name,
818					  vector<ArrayBuffer<deUint8> >&	levels,
819					  const ImageInfo&					info,
820					  deUint32							moreRestrictiveFormat)
821{
822	const int		texelBlockSize			= getTexelBlockSize(info.getFormat());
823	const IVec3		texelBlockPixelSize		= getTexelBlockPixelSize(info.getFormat());
824
825	levels.resize(getLevelCount(info));
826
827	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
828	GLU_EXPECT_NO_ERROR(gl.getError(), "Setting pixel store aligment failed.");
829
830	gl.bindTexture(info.getTarget(), name);
831	GLU_EXPECT_NO_ERROR(gl.getError(), "Binding texture failed.");
832
833	for (int levelNdx = 0; levelNdx < getLevelCount(info); levelNdx++)
834	{
835		ArrayBuffer<deUint8>&	level					= levels[levelNdx];
836
837		const int				faceCount				= (info.getTarget() == GL_TEXTURE_CUBE_MAP ? 6 : 1);
838
839		const IVec3				levelPixelSize			= getLevelSize(info.getTarget(), info.getSize(), levelNdx);
840		const IVec3				levelTexelBlockSize		= divRoundUp(levelPixelSize, texelBlockPixelSize);
841		const int				levelTexelBlockCount	= levelTexelBlockSize.x() * levelTexelBlockSize.y() * levelTexelBlockSize.z();
842		const int				levelSize				= levelTexelBlockCount * texelBlockSize;
843
844		level.setStorage(levelSize * faceCount);
845
846		for (int faceNdx = 0; faceNdx < faceCount; faceNdx++)
847		{
848			genTexel(rng, moreRestrictiveFormat, texelBlockSize, levelTexelBlockCount, level.getElementPtr(faceNdx * levelSize));
849
850			genericTexImage(gl, info.getTarget(), faceNdx, levelNdx, levelPixelSize, info.getFormat(), levelSize, level.getElementPtr(faceNdx * levelSize));
851		}
852	}
853
854	gl.texParameteri(info.getTarget(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
855	gl.texParameteri(info.getTarget(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
856
857	if (info.getTarget() == GL_TEXTURE_3D)
858		gl.texParameteri(info.getTarget(), GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
859
860	gl.texParameteri(info.getTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
861	gl.texParameteri(info.getTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
862	GLU_EXPECT_NO_ERROR(gl.getError(), "Setting texture parameters failed");
863
864	gl.bindTexture(info.getTarget(), 0);
865	GLU_EXPECT_NO_ERROR(gl.getError(), "Unbinding texture failed.");
866}
867
868void genRenderbufferImage (const glw::Functions&			gl,
869						   de::Random&						rng,
870						   deUint32							name,
871						   vector<ArrayBuffer<deUint8> >&	levels,
872						   const ImageInfo&					info,
873						   deUint32							moreRestrictiveFormat)
874{
875	const IVec3					size	= info.getSize();
876	const tcu::TextureFormat	format	= glu::mapGLInternalFormat(info.getFormat());
877
878	DE_ASSERT(info.getTarget() == GL_RENDERBUFFER);
879	DE_ASSERT(info.getSize().z() == 1);
880	DE_ASSERT(getLevelCount(info) == 1);
881	DE_ASSERT(!glu::isCompressedFormat(info.getFormat()));
882
883	glu::Framebuffer framebuffer(gl);
884
885	levels.resize(1);
886	levels[0].setStorage(format.getPixelSize() * size.x() * size.y());
887	tcu::PixelBufferAccess refAccess(format, size.x(), size.y(), 1, levels[0].getPtr());
888
889	gl.bindRenderbuffer(GL_RENDERBUFFER, name);
890	gl.renderbufferStorage(GL_RENDERBUFFER, info.getFormat(), info.getSize().x(), info.getSize().y());
891	GLU_EXPECT_NO_ERROR(gl.getError(), "Binding and setting storage for renderbuffer failed.");
892
893	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
894	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, name);
895	GLU_EXPECT_NO_ERROR(gl.getError(), "Binding framebuffer and attaching renderbuffer failed.");
896
897	{
898		vector<deUint8> texelBlock(format.getPixelSize());
899
900		if (isFixedPointFormat(info.getFormat()))
901		{
902			// All zeroes is only bit pattern that fixed point values can be
903			// cleared to and that is valid floating point value.
904			if (isFloatFormat(moreRestrictiveFormat))
905				deMemset(&texelBlock[0], 0x0, texelBlock.size());
906			else
907			{
908				// Fixed point values can be only cleared to all 0 or 1.
909				const deInt32 fill = rng.getBool() ? 0xFF : 0x0;
910				deMemset(&texelBlock[0], fill, texelBlock.size());
911			}
912		}
913		else
914			genTexel(rng, moreRestrictiveFormat, format.getPixelSize(), 1, &(texelBlock[0]));
915
916		{
917			const tcu::ConstPixelBufferAccess texelAccess (format, 1, 1, 1, &(texelBlock[0]));
918
919			if (isIntFormat(info.getFormat()))
920			{
921				const tcu::IVec4 color = texelAccess.getPixelInt(0, 0, 0);
922
923				gl.clearBufferiv(GL_COLOR, 0, (const deInt32*)&color);
924				GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear renderbuffer.");
925
926				DE_ASSERT(!tcu::isSRGB(format));
927				tcu::clear(refAccess, color);
928			}
929			else if (isUintFormat(info.getFormat()))
930			{
931				const tcu::IVec4 color = texelAccess.getPixelInt(0, 0, 0);
932
933				gl.clearBufferuiv(GL_COLOR, 0, (const deUint32*)&color);
934				GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear renderbuffer.");
935
936				DE_ASSERT(!tcu::isSRGB(format));
937				tcu::clear(refAccess, color);
938			}
939			else
940			{
941				const tcu::Vec4 rawColor	= texelAccess.getPixel(0, 0, 0);
942				const tcu::Vec4 linearColor	= (tcu::isSRGB(format) ? tcu::sRGBToLinear(rawColor) : rawColor);
943
944				// rawColor bit pattern has been chosen to be "safe" in the destination format. For sRGB
945				// formats, the clear color is in linear space. Since we want the resulting bit pattern
946				// to be safe after implementation linear->sRGB transform, we must apply the inverting
947				// transform to the clear color.
948
949				if (isFloatFormat(info.getFormat()))
950				{
951					gl.clearBufferfv(GL_COLOR, 0, (const float*)&linearColor);
952				}
953				else
954				{
955					// fixed-point
956					gl.clearColor(linearColor.x(), linearColor.y(), linearColor.z(), linearColor.w());
957					gl.clear(GL_COLOR_BUFFER_BIT);
958				}
959				GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear renderbuffer.");
960
961				tcu::clear(refAccess, rawColor);
962			}
963		}
964	}
965
966	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
967	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
968	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind renderbufer and framebuffer.");
969}
970
971void genImage (const glw::Functions&			gl,
972			   de::Random&						rng,
973			   deUint32							name,
974			   vector<ArrayBuffer<deUint8> >&	levels,
975			   const ImageInfo&					info,
976			   deUint32							moreRestrictiveFormat)
977{
978	if (isTextureTarget(info.getTarget()))
979		genTextureImage(gl, rng, name, levels, info, moreRestrictiveFormat);
980	else
981		genRenderbufferImage(gl, rng, name, levels, info, moreRestrictiveFormat);
982}
983
984IVec3 getTexelBlockStride (const ImageInfo& info, int level)
985{
986	const IVec3	size					= getLevelSize(info.getTarget(), info.getSize(), level);
987	const int	texelBlockSize			= getTexelBlockSize(info.getFormat());
988	const IVec3 texelBlockPixelSize		= getTexelBlockPixelSize(info.getFormat());
989	const IVec3 textureTexelBlockSize	= divRoundUp(size, texelBlockPixelSize);
990
991	return IVec3(texelBlockSize, textureTexelBlockSize.x() * texelBlockSize, textureTexelBlockSize.x() * textureTexelBlockSize.y() * texelBlockSize);
992}
993
994int sumComponents (const IVec3& v)
995{
996	int s = 0;
997
998	for (int i = 0; i < 3; i++)
999		s += v[i];
1000
1001	return s;
1002}
1003
1004void copyImageData (vector<ArrayBuffer<deUint8> >&			dstImageData,
1005					const ImageInfo&						dstImageInfo,
1006					int										dstLevel,
1007					const IVec3&							dstPos,
1008
1009					const vector<ArrayBuffer<deUint8> >&	srcImageData,
1010					const ImageInfo&						srcImageInfo,
1011					int										srcLevel,
1012					const IVec3&							srcPos,
1013
1014					const IVec3&							copySize)
1015{
1016	const ArrayBuffer<deUint8>&	srcLevelData			= srcImageData[srcLevel];
1017	ArrayBuffer<deUint8>&		dstLevelData			= dstImageData[dstLevel];
1018
1019	const IVec3					srcTexelBlockPixelSize	= getTexelBlockPixelSize(srcImageInfo.getFormat());
1020	const int					srcTexelBlockSize		= getTexelBlockSize(srcImageInfo.getFormat());
1021	const IVec3					srcTexelPos				= srcPos / srcTexelBlockPixelSize;
1022	const IVec3					srcTexelBlockStride		= getTexelBlockStride(srcImageInfo, srcLevel);
1023
1024	const IVec3					dstTexelBlockPixelSize	= getTexelBlockPixelSize(dstImageInfo.getFormat());
1025	const int					dstTexelBlockSize		= getTexelBlockSize(dstImageInfo.getFormat());
1026	const IVec3					dstTexelPos				= dstPos / dstTexelBlockPixelSize;
1027	const IVec3					dstTexelBlockStride		= getTexelBlockStride(dstImageInfo, dstLevel);
1028
1029	const IVec3					copyTexelBlockCount		= copySize / srcTexelBlockPixelSize;
1030	const int					texelBlockSize			= srcTexelBlockSize;
1031
1032	DE_ASSERT(srcTexelBlockSize == dstTexelBlockSize);
1033	DE_UNREF(dstTexelBlockSize);
1034
1035	DE_ASSERT((copySize.x() % srcTexelBlockPixelSize.x()) == 0);
1036	DE_ASSERT((copySize.y() % srcTexelBlockPixelSize.y()) == 0);
1037	DE_ASSERT((copySize.z() % srcTexelBlockPixelSize.z()) == 0);
1038
1039	DE_ASSERT((srcPos.x() % srcTexelBlockPixelSize.x()) == 0);
1040	DE_ASSERT((srcPos.y() % srcTexelBlockPixelSize.y()) == 0);
1041	DE_ASSERT((srcPos.z() % srcTexelBlockPixelSize.z()) == 0);
1042
1043	for (int z = 0; z < copyTexelBlockCount.z(); z++)
1044	for (int y = 0; y < copyTexelBlockCount.y(); y++)
1045	{
1046		const IVec3				blockPos		(0, y, z);
1047		const deUint8* const	srcPtr			= srcLevelData.getElementPtr(sumComponents((srcTexelPos + blockPos) * srcTexelBlockStride));
1048		deUint8* const			dstPtr			= dstLevelData.getElementPtr(sumComponents((dstTexelPos + blockPos) * dstTexelBlockStride));
1049		const int				copyLineSize	= copyTexelBlockCount.x() * texelBlockSize;
1050
1051		deMemcpy(dstPtr, srcPtr, copyLineSize);
1052	}
1053}
1054
1055vector<tcu::ConstPixelBufferAccess> getLevelAccesses (const vector<ArrayBuffer<deUint8> >& data, const ImageInfo& info)
1056{
1057	const tcu::TextureFormat			format	= glu::mapGLInternalFormat(info.getFormat());
1058	const IVec3							size	= info.getSize();
1059
1060	vector<tcu::ConstPixelBufferAccess>	result;
1061
1062	DE_ASSERT((int)data.size() == getLevelCount(info));
1063
1064	for (int level = 0; level < (int)data.size(); level++)
1065	{
1066		const IVec3 levelSize = getLevelSize(info.getTarget(), size, level);
1067
1068		result.push_back(tcu::ConstPixelBufferAccess(format, levelSize.x(), levelSize.y(), levelSize.z(), data[level].getPtr()));
1069	}
1070
1071	return result;
1072}
1073
1074vector<tcu::ConstPixelBufferAccess> getCubeLevelAccesses (const vector<ArrayBuffer<deUint8> >&	data,
1075														  const ImageInfo&						info,
1076														  int									faceNdx)
1077{
1078	const tcu::TextureFormat			format				= glu::mapGLInternalFormat(info.getFormat());
1079	const IVec3							size				= info.getSize();
1080	const int							texelBlockSize		= getTexelBlockSize(info.getFormat());
1081	const IVec3							texelBlockPixelSize = getTexelBlockPixelSize(info.getFormat());
1082	vector<tcu::ConstPixelBufferAccess>	result;
1083
1084	DE_ASSERT(info.getTarget() == GL_TEXTURE_CUBE_MAP);
1085	DE_ASSERT((int)data.size() == getLevelCount(info));
1086
1087	for (int level = 0; level < (int)data.size(); level++)
1088	{
1089		const IVec3 levelPixelSize			= getLevelSize(info.getTarget(), size, level);
1090		const IVec3	levelTexelBlockSize		= divRoundUp(levelPixelSize, texelBlockPixelSize);
1091		const int	levelTexelBlockCount	= levelTexelBlockSize.x() * levelTexelBlockSize.y() * levelTexelBlockSize.z();
1092		const int	levelSize				= levelTexelBlockCount * texelBlockSize;
1093
1094		result.push_back(tcu::ConstPixelBufferAccess(format, levelPixelSize.x(), levelPixelSize.y(), levelPixelSize.z(), data[level].getElementPtr(levelSize * faceNdx)));
1095	}
1096
1097	return result;
1098}
1099
1100void copyImage (const glw::Functions&					gl,
1101
1102				deUint32								dstName,
1103				vector<ArrayBuffer<deUint8> >&			dstImageData,
1104				const ImageInfo&						dstImageInfo,
1105				int										dstLevel,
1106				const IVec3&							dstPos,
1107
1108				deUint32								srcName,
1109				const vector<ArrayBuffer<deUint8> >&	srcImageData,
1110				const ImageInfo&						srcImageInfo,
1111				int										srcLevel,
1112				const IVec3&							srcPos,
1113
1114				const IVec3&							copySize)
1115{
1116	gl.copyImageSubData(srcName, srcImageInfo.getTarget(), srcLevel, srcPos.x(), srcPos.y(), srcPos.z(),
1117						dstName, dstImageInfo.getTarget(), dstLevel, dstPos.x(), dstPos.y(), dstPos.z(),
1118						copySize.x(), copySize.y(), copySize.z());
1119
1120	GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyImageSubData failed.");
1121
1122	copyImageData(dstImageData, dstImageInfo, dstLevel, dstPos,
1123				  srcImageData, srcImageInfo, srcLevel, srcPos, copySize);
1124}
1125
1126template<class TextureView>
1127void renderTexture (glu::RenderContext&		renderContext,
1128					TextureRenderer&		renderer,
1129					ReferenceParams&		renderParams,
1130					tcu::ResultCollector&	results,
1131					de::Random&				rng,
1132					const TextureView&		refTexture,
1133					const Verify			verify,
1134					TextureImageIterator&	imageIterator,
1135					tcu::TestLog&			log)
1136{
1137	const tcu::RenderTarget&	renderTarget		= renderContext.getRenderTarget();
1138	const tcu::RGBA				threshold			= renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
1139	const glw::Functions&		gl					= renderContext.getFunctions();
1140	const IVec2					renderTargetSize	= IVec2(renderTarget.getWidth(), renderTarget.getHeight());
1141
1142	while (imageIterator.hasNextImage())
1143	{
1144		// \note: Reserve space upfront to avoid assigning tcu::Surface, which incurs buffer mem copy. Using a
1145		// conservative estimate for simplicity
1146		const int				imagesOnLevel	= imageIterator.getLevelImageCount();
1147		const int				imageEstimate	= (imageIterator.getMipLevelCount() - imageIterator.getMipLevel()) * imagesOnLevel;
1148		RandomizedRenderGrid	renderGrid		(renderTargetSize, imageIterator.getSize(), imageEstimate, rng.getUint32());
1149		vector<CellContents>	cellContents	(renderGrid.getCellCount());
1150		int						cellsUsed		= 0;
1151
1152		// \note: Ordering of conditions is significant. If put the other way around, the code would skip one of the
1153		// images if the grid runs out of cells before the texture runs out of images. Advancing one grid cell over the
1154		// needed number has no negative impact.
1155		while (renderGrid.nextCell() && imageIterator.nextImage())
1156		{
1157			const int		level	  = imageIterator.getMipLevel();
1158			const IVec2		levelSize = imageIterator.getSize();
1159			const IVec2		origin	  = renderGrid.getOrigin();
1160			vector<float>	texCoord;
1161
1162			DE_ASSERT(imageIterator.getTarget() != GL_TEXTURE_CUBE_MAP || levelSize.x() >= 4 || levelSize.y() >= 4);
1163
1164			renderParams.baseLevel	= level;
1165			renderParams.maxLevel	= level;
1166
1167			gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_BASE_LEVEL, level);
1168			gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_MAX_LEVEL, level);
1169
1170			computeQuadTexCoords(texCoord, imageIterator);
1171
1172			// Setup base viewport.
1173			gl.viewport(origin.x(), origin.y(), levelSize.x(), levelSize.y());
1174
1175			// Draw.
1176			renderer.renderQuad(0, &texCoord[0], renderParams);
1177			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render.");
1178
1179			if (verify == VERIFY_COMPARE_REFERENCE)
1180			{
1181				const int	target					= imageIterator.getTarget();
1182				const int	imageIndex				= imageIterator.getCurrentImage();
1183
1184				cellContents[cellsUsed].origin		= origin;
1185				cellContents[cellsUsed].name		= getTextureImageName(target, level, imageIndex);
1186				cellContents[cellsUsed].description	= getTextureImageDescription(target, level, imageIndex);
1187
1188				cellContents[cellsUsed].reference.setSize(levelSize.x(), levelSize.y());
1189
1190				// Compute reference.
1191				sampleTexture(tcu::SurfaceAccess(cellContents[cellsUsed].reference, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
1192				cellsUsed++;
1193			}
1194		}
1195
1196		if (cellsUsed > 0)
1197		{
1198			const IVec4		boundingBox		= renderGrid.getUsedAreaBoundingBox();
1199			tcu::Surface	renderedFrame	(boundingBox[2], boundingBox[3]);
1200
1201			glu::readPixels(renderContext, boundingBox.x(), boundingBox.y(), renderedFrame.getAccess());
1202			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to read pixels.");
1203
1204			for (int idx = 0; idx < cellsUsed; idx++)
1205			{
1206				const CellContents&					cell		 (cellContents[idx]);
1207				const IVec2							cellOrigin	 = cell.origin - boundingBox.toWidth<2>();
1208				const tcu::ConstPixelBufferAccess	resultAccess = getSubregion(renderedFrame.getAccess(), cellOrigin.x(), cellOrigin.y(), cell.reference.getWidth(), cell.reference.getHeight());
1209
1210				if (!intThresholdCompare(log, cell.name.c_str(), cell.description.c_str(), cell.reference.getAccess(), resultAccess, threshold.toIVec().cast<deUint32>(), tcu::COMPARE_LOG_ON_ERROR))
1211					results.fail("Image comparison of " + cell.description + " failed.");
1212				else
1213					log << TestLog::Message << "Image comparison of " << cell.description << " passed." << TestLog::EndMessage;;
1214			}
1215		}
1216	}
1217
1218	gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_BASE_LEVEL, 0);
1219	gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_MAX_LEVEL, 1000);
1220}
1221
1222void renderTexture2DView (tcu::TestContext&			testContext,
1223						  glu::RenderContext&		renderContext,
1224						  TextureRenderer&			renderer,
1225						  tcu::ResultCollector&		results,
1226						  de::Random&				rng,
1227						  deUint32					name,
1228						  const ImageInfo&			info,
1229						  const tcu::Texture2DView&	refTexture,
1230						  Verify					verify)
1231{
1232	tcu::TestLog&					log				= testContext.getLog();
1233	const glw::Functions&			gl				= renderContext.getFunctions();
1234	const tcu::TextureFormat		format			= refTexture.getLevel(0).getFormat();
1235	const tcu::TextureFormatInfo	spec			= tcu::getTextureFormatInfo(format);
1236
1237	ReferenceParams					renderParams	(TEXTURETYPE_2D);
1238	TextureImageIterator			imageIterator	(info, getLevelCount(info));
1239
1240	renderParams.samplerType	= getSamplerType(format);
1241	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
1242	renderParams.colorScale		= spec.lookupScale;
1243	renderParams.colorBias		= spec.lookupBias;
1244
1245	gl.activeTexture(GL_TEXTURE0);
1246	gl.bindTexture(GL_TEXTURE_2D, name);
1247	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind texture.");
1248
1249	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1250	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1251	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1252	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1253	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
1254
1255	renderTexture<tcu::Texture2DView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
1256
1257	gl.bindTexture(GL_TEXTURE_2D, 0);
1258	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
1259}
1260
1261void decompressTextureLevel (const tcu::TexDecompressionParams&		params,
1262							 ArrayBuffer<deUint8>&					levelData,
1263							 tcu::PixelBufferAccess&				levelAccess,
1264							 const tcu::CompressedTexFormat&		compressedFormat,
1265							 const tcu::TextureFormat&				decompressedFormat,
1266							 const IVec3&							levelPixelSize,
1267							 const void*							data)
1268{
1269	levelData.setStorage(levelPixelSize.x() * levelPixelSize.y() * levelPixelSize.z() * decompressedFormat.getPixelSize());
1270	levelAccess = tcu::PixelBufferAccess(decompressedFormat, levelPixelSize.x(), levelPixelSize.y(), levelPixelSize.z(), levelData.getPtr());
1271
1272	tcu::decompress(levelAccess, compressedFormat, (const deUint8*)data, params);
1273}
1274
1275void decompressTexture (vector<ArrayBuffer<deUint8> >&			levelDatas,
1276						vector<tcu::PixelBufferAccess>&			levelAccesses,
1277						glu::RenderContext&						renderContext,
1278						const ImageInfo&						info,
1279						const vector<ArrayBuffer<deUint8> >&	data)
1280{
1281	const tcu::CompressedTexFormat	compressedFormat	= glu::mapGLCompressedTexFormat(info.getFormat());
1282	const tcu::TextureFormat		decompressedFormat	= tcu::getUncompressedFormat(compressedFormat);
1283	const IVec3						size				= info.getSize();
1284	const bool						isES32				= glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
1285
1286	de::UniquePtr<glu::ContextInfo>	ctxInfo				(glu::ContextInfo::create(renderContext));
1287	tcu::TexDecompressionParams		decompressParams;
1288
1289	if (tcu::isAstcFormat(compressedFormat))
1290	{
1291		if (ctxInfo->isExtensionSupported("GL_KHR_texture_compression_astc_hdr") && !tcu::isAstcSRGBFormat(compressedFormat))
1292			decompressParams = tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_HDR);
1293		else if (isES32 || ctxInfo->isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
1294			decompressParams = tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_LDR);
1295		else
1296			DE_ASSERT(false);
1297	}
1298
1299	levelDatas.resize(getLevelCount(info));
1300	levelAccesses.resize(getLevelCount(info));
1301
1302	for (int level = 0; level < getLevelCount(info); level++)
1303	{
1304		const IVec3					levelPixelSize	= getLevelSize(info.getTarget(), size, level);
1305		de::ArrayBuffer<deUint8>&	levelData		= levelDatas[level];
1306		tcu::PixelBufferAccess&		levelAccess		= levelAccesses[level];
1307
1308		decompressTextureLevel(decompressParams, levelData, levelAccess, compressedFormat, decompressedFormat, levelPixelSize, data[level].getPtr());
1309	}
1310}
1311
1312void renderTexture2D (tcu::TestContext&						testContext,
1313					  glu::RenderContext&					renderContext,
1314					  TextureRenderer&						textureRenderer,
1315					  tcu::ResultCollector&					results,
1316					  de::Random&							rng,
1317					  deUint32								name,
1318					  const vector<ArrayBuffer<deUint8> >&	data,
1319					  const ImageInfo&						info,
1320					  Verify								verify)
1321{
1322	if (glu::isCompressedFormat(info.getFormat()))
1323	{
1324		vector<de::ArrayBuffer<deUint8> >	levelDatas;
1325		vector<tcu::PixelBufferAccess>		levelAccesses;
1326
1327		decompressTexture(levelDatas, levelAccesses, renderContext, info, data);
1328
1329		{
1330			const tcu::Texture2DView refTexture((int)levelAccesses.size(), &(levelAccesses[0]));
1331
1332			renderTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
1333		}
1334	}
1335	else
1336	{
1337		const vector<tcu::ConstPixelBufferAccess>	levelAccesses	= getLevelAccesses(data, info);
1338		const tcu::Texture2DView					refTexture		((int)levelAccesses.size(), &(levelAccesses[0]));
1339
1340		renderTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
1341	}
1342}
1343
1344void renderTexture3DView (tcu::TestContext&			testContext,
1345						  glu::RenderContext&		renderContext,
1346						  TextureRenderer&			renderer,
1347						  tcu::ResultCollector&		results,
1348						  de::Random&				rng,
1349						  deUint32					name,
1350						  const ImageInfo&			info,
1351						  const tcu::Texture3DView&	refTexture,
1352						  Verify					verify)
1353{
1354	tcu::TestLog&					log				= testContext.getLog();
1355	const glw::Functions&			gl				= renderContext.getFunctions();
1356	const tcu::TextureFormat		format			= refTexture.getLevel(0).getFormat();
1357	const tcu::TextureFormatInfo	spec			= tcu::getTextureFormatInfo(format);
1358
1359	ReferenceParams					renderParams	(TEXTURETYPE_3D);
1360	TextureImageIterator			imageIterator	(info, getLevelCount(info));
1361
1362	renderParams.samplerType	= getSamplerType(format);
1363	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
1364	renderParams.colorScale		= spec.lookupScale;
1365	renderParams.colorBias		= spec.lookupBias;
1366
1367	gl.activeTexture(GL_TEXTURE0);
1368	gl.bindTexture(GL_TEXTURE_3D, name);
1369	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind texture.");
1370
1371	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1372	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1373	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
1374	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1375	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1376	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
1377
1378	renderTexture<tcu::Texture3DView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
1379
1380	gl.bindTexture(GL_TEXTURE_3D, 0);
1381	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
1382}
1383
1384void renderTexture3D (tcu::TestContext&						testContext,
1385					  glu::RenderContext&					renderContext,
1386					  TextureRenderer&						textureRenderer,
1387					  tcu::ResultCollector&					results,
1388					  de::Random&							rng,
1389					  deUint32								name,
1390					  const vector<ArrayBuffer<deUint8> >&	data,
1391					  const ImageInfo&						info,
1392				      Verify								verify)
1393{
1394	if (glu::isCompressedFormat(info.getFormat()))
1395	{
1396		vector<de::ArrayBuffer<deUint8> >	levelDatas;
1397		vector<tcu::PixelBufferAccess>		levelAccesses;
1398
1399		decompressTexture(levelDatas, levelAccesses, renderContext, info, data);
1400
1401		{
1402			const tcu::Texture3DView refTexture((int)levelAccesses.size(), &(levelAccesses[0]));
1403
1404			renderTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
1405		}
1406	}
1407	else
1408	{
1409		const vector<tcu::ConstPixelBufferAccess>	levelAccesses	= getLevelAccesses(data, info);
1410		const tcu::Texture3DView					refTexture		((int)levelAccesses.size(), &(levelAccesses[0]));
1411
1412		renderTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
1413	}
1414}
1415
1416void renderTextureCubemapView (tcu::TestContext&			testContext,
1417							   glu::RenderContext&			renderContext,
1418							   TextureRenderer&				renderer,
1419							   tcu::ResultCollector&		results,
1420							   de::Random&					rng,
1421							   deUint32						name,
1422							   const ImageInfo&				info,
1423							   const tcu::TextureCubeView&	refTexture,
1424							   Verify						verify)
1425{
1426	tcu::TestLog&					log				= testContext.getLog();
1427	const glw::Functions&			gl				= renderContext.getFunctions();
1428	const tcu::TextureFormat		format			= refTexture.getLevelFace(0, tcu::CUBEFACE_POSITIVE_X).getFormat();
1429	const tcu::TextureFormatInfo	spec			= tcu::getTextureFormatInfo(format);
1430
1431	ReferenceParams					renderParams	(TEXTURETYPE_CUBE);
1432    // \note It seems we can't reliably sample two smallest texture levels with cubemaps
1433	TextureImageIterator			imageIterator	(info, getLevelCount(info) - 2);
1434
1435	renderParams.samplerType	= getSamplerType(format);
1436	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
1437	renderParams.colorScale		= spec.lookupScale;
1438	renderParams.colorBias		= spec.lookupBias;
1439
1440	gl.activeTexture(GL_TEXTURE0);
1441	gl.bindTexture(GL_TEXTURE_CUBE_MAP, name);
1442	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind texture.");
1443
1444	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1445	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1446	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1447	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1448	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
1449
1450	renderTexture<tcu::TextureCubeView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
1451
1452	gl.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
1453	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
1454}
1455
1456void renderTextureCubemap (tcu::TestContext&					testContext,
1457						   glu::RenderContext&					renderContext,
1458						   TextureRenderer&						textureRenderer,
1459						   tcu::ResultCollector&				results,
1460						   de::Random&							rng,
1461						   deUint32								name,
1462						   const vector<ArrayBuffer<deUint8> >&	data,
1463						   const ImageInfo&						info,
1464						   Verify								verify)
1465{
1466	if (glu::isCompressedFormat(info.getFormat()))
1467	{
1468		const tcu::CompressedTexFormat&	compressedFormat	= glu::mapGLCompressedTexFormat(info.getFormat());
1469		const tcu::TextureFormat&		decompressedFormat	= tcu::getUncompressedFormat(compressedFormat);
1470
1471		const int						texelBlockSize		= getTexelBlockSize(info.getFormat());
1472		const IVec3						texelBlockPixelSize = getTexelBlockPixelSize(info.getFormat());
1473
1474		const bool						isES32				= glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
1475
1476		vector<tcu::PixelBufferAccess>	levelAccesses[6];
1477		vector<ArrayBuffer<deUint8> >	levelDatas[6];
1478		de::UniquePtr<glu::ContextInfo>	ctxInfo				(glu::ContextInfo::create(renderContext));
1479		tcu::TexDecompressionParams		decompressParams;
1480
1481		if (tcu::isAstcFormat(compressedFormat))
1482		{
1483			if (ctxInfo->isExtensionSupported("GL_KHR_texture_compression_astc_hdr") && !tcu::isAstcSRGBFormat(compressedFormat))
1484				decompressParams = tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_HDR);
1485			else if (isES32 || ctxInfo->isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
1486				decompressParams = tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_LDR);
1487			else
1488				DE_ASSERT(false);
1489		}
1490
1491		for (int faceNdx = 0; faceNdx < 6; faceNdx++)
1492		{
1493			levelAccesses[faceNdx].resize(getLevelCount(info));
1494			levelDatas[faceNdx].resize(getLevelCount(info));
1495		}
1496
1497		for (int level = 0; level < getLevelCount(info); level++)
1498		{
1499			for (int faceNdx = 0; faceNdx < 6; faceNdx++)
1500			{
1501				const IVec3				levelPixelSize			= getLevelSize(info.getTarget(), info.getSize(), level);
1502				const IVec3				levelTexelBlockSize		= divRoundUp(levelPixelSize, texelBlockPixelSize);
1503				const int				levelTexelBlockCount	= levelTexelBlockSize.x() * levelTexelBlockSize.y() * levelTexelBlockSize.z();
1504				const int				levelSize				= levelTexelBlockCount * texelBlockSize;
1505
1506				const deUint8*			dataPtr					= data[level].getElementPtr(faceNdx * levelSize);
1507				tcu::PixelBufferAccess& levelAccess				= levelAccesses[faceNdx][level];
1508				ArrayBuffer<deUint8>&	levelData				= levelDatas[faceNdx][level];
1509
1510				decompressTextureLevel(decompressParams, levelData, levelAccess, compressedFormat, decompressedFormat, levelPixelSize, dataPtr);
1511			}
1512		}
1513
1514		const tcu::ConstPixelBufferAccess* levels[6];
1515
1516		for (int faceNdx = 0; faceNdx < 6; faceNdx++)
1517			levels[glu::getCubeFaceFromGL(mapFaceNdxToFace(faceNdx))] = &(levelAccesses[faceNdx][0]);
1518
1519		{
1520			const tcu::TextureCubeView refTexture(getLevelCount(info), levels);
1521
1522			renderTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
1523		}
1524	}
1525	else
1526	{
1527		const vector<tcu::ConstPixelBufferAccess> levelAccesses[6] =
1528		{
1529			getCubeLevelAccesses(data, info, 0),
1530			getCubeLevelAccesses(data, info, 1),
1531			getCubeLevelAccesses(data, info, 2),
1532			getCubeLevelAccesses(data, info, 3),
1533			getCubeLevelAccesses(data, info, 4),
1534			getCubeLevelAccesses(data, info, 5),
1535		};
1536
1537		const tcu::ConstPixelBufferAccess* levels[6];
1538
1539		for (int faceNdx = 0; faceNdx < 6; faceNdx++)
1540			levels[glu::getCubeFaceFromGL(mapFaceNdxToFace(faceNdx))] = &(levelAccesses[faceNdx][0]);
1541
1542		{
1543			const tcu::TextureCubeView refTexture(getLevelCount(info), levels);
1544
1545			renderTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
1546		}
1547	}
1548}
1549
1550void renderTexture2DArrayView (tcu::TestContext&				testContext,
1551							   glu::RenderContext&				renderContext,
1552							   TextureRenderer&					renderer,
1553							   tcu::ResultCollector&			results,
1554							   de::Random&						rng,
1555							   deUint32							name,
1556							   const ImageInfo&					info,
1557							   const tcu::Texture2DArrayView&	refTexture,
1558							   Verify							verify)
1559{
1560	tcu::TestLog&					log				= testContext.getLog();
1561	const glw::Functions&			gl				= renderContext.getFunctions();
1562	const tcu::TextureFormat		format			= refTexture.getLevel(0).getFormat();
1563	const tcu::TextureFormatInfo	spec			= tcu::getTextureFormatInfo(format);
1564
1565	ReferenceParams					renderParams	(TEXTURETYPE_2D_ARRAY);
1566	TextureImageIterator			imageIterator	(info, getLevelCount(info));
1567
1568	renderParams.samplerType	= getSamplerType(format);
1569	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
1570	renderParams.colorScale		= spec.lookupScale;
1571	renderParams.colorBias		= spec.lookupBias;
1572
1573	gl.activeTexture(GL_TEXTURE0);
1574	gl.bindTexture(GL_TEXTURE_2D_ARRAY, name);
1575	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind texture.");
1576
1577	gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1578	gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1579	gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1580	gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1581	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
1582
1583	renderTexture<tcu::Texture2DArrayView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
1584
1585	gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
1586	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
1587}
1588
1589void renderTexture2DArray (tcu::TestContext&					testContext,
1590						   glu::RenderContext&					renderContext,
1591						   TextureRenderer&						textureRenderer,
1592						   tcu::ResultCollector&				results,
1593						   de::Random&							rng,
1594						   deUint32								name,
1595						   const vector<ArrayBuffer<deUint8> >&	data,
1596						   const ImageInfo&						info,
1597						   Verify								verify)
1598{
1599	if (glu::isCompressedFormat(info.getFormat()))
1600	{
1601		vector<de::ArrayBuffer<deUint8> >	levelDatas;
1602		vector<tcu::PixelBufferAccess>		levelAccesses;
1603
1604		decompressTexture(levelDatas, levelAccesses, renderContext, info, data);
1605
1606		{
1607			const tcu::Texture2DArrayView refTexture((int)levelAccesses.size(), &(levelAccesses[0]));
1608
1609			renderTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
1610		}
1611	}
1612	else
1613	{
1614		const vector<tcu::ConstPixelBufferAccess>	levelAccesses	= getLevelAccesses(data, info);
1615		const tcu::Texture2DArrayView				refTexture		((int)levelAccesses.size(), &(levelAccesses[0]));
1616
1617		renderTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
1618	}
1619}
1620
1621tcu::TextureFormat getReadPixelFormat (const tcu::TextureFormat& format)
1622{
1623	switch (tcu::getTextureChannelClass(format.type))
1624	{
1625		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1626		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1627		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1628			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1629
1630		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1631			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
1632
1633		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1634			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
1635
1636		default:
1637			DE_ASSERT(false);
1638			return tcu::TextureFormat();
1639	}
1640}
1641
1642Vec4 calculateThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
1643{
1644	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
1645	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
1646
1647	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
1648	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
1649
1650	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
1651	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
1652
1653	{
1654		const tcu::IVec4	srcBits		= tcu::getTextureFormatBitDepth(sourceFormat);
1655		const tcu::IVec4	readBits	= tcu::getTextureFormatBitDepth(readPixelsFormat);
1656
1657		return Vec4(1.0f) / ((tcu::IVec4(1) << (tcu::min(srcBits, readBits))) - tcu::IVec4(1)).cast<float>();
1658	}
1659}
1660
1661void renderRenderbuffer (tcu::TestContext&						testContext,
1662						 glu::RenderContext&					renderContext,
1663						 tcu::ResultCollector&					results,
1664						 deUint32								name,
1665						 const vector<ArrayBuffer<deUint8> >&	data,
1666						 const ImageInfo&						info,
1667						 Verify									verify)
1668{
1669	const glw::Functions&				gl					= renderContext.getFunctions();
1670	TestLog&							log					= testContext.getLog();
1671
1672	const tcu::TextureFormat			format				= glu::mapGLInternalFormat(info.getFormat());
1673	const IVec3							size				= info.getSize();
1674	const tcu::ConstPixelBufferAccess	refRenderbuffer		(format, size.x(), size.y(), 1, data[0].getPtr());
1675	const tcu::TextureFormat			readPixelsFormat	= getReadPixelFormat(format);
1676	tcu::TextureLevel					renderbuffer		(readPixelsFormat, size.x(), size.y());
1677
1678	DE_ASSERT(size.z() == 1);
1679	DE_ASSERT(data.size() == 1);
1680
1681	{
1682		glu::Framebuffer framebuffer(gl);
1683
1684		gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
1685		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create and bind framebuffer.");
1686
1687		gl.bindRenderbuffer(GL_RENDERBUFFER, name);
1688		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, name);
1689		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind and attach renderbuffer to framebuffer.");
1690
1691		if (verify)
1692			glu::readPixels(renderContext, 0, 0, renderbuffer.getAccess());
1693
1694		gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
1695		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1696		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind renderbuffer and framebuffer.");
1697	}
1698
1699	if (verify == VERIFY_COMPARE_REFERENCE)
1700	{
1701		if (isFloatFormat(info.getFormat()))
1702		{
1703			const tcu::UVec4 threshold (2, 2, 2, 2);
1704
1705			if (!(tcu::floatUlpThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
1706				results.fail("Image comparison failed.");
1707			else
1708				log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
1709		}
1710		else if (isIntFormat(info.getFormat()) || isUintFormat(info.getFormat()))
1711		{
1712			const tcu::UVec4 threshold (1, 1, 1, 1);
1713
1714			if (!(tcu::intThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
1715				results.fail("Image comparison failed.");
1716			else
1717				log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
1718		}
1719		else
1720		{
1721			const Vec4 threshold = calculateThreshold(format, readPixelsFormat);
1722
1723			if (!(tcu::floatThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
1724				results.fail("Image comparison failed.");
1725			else
1726				log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
1727		}
1728	}
1729}
1730
1731void render (tcu::TestContext&						testContext,
1732			 glu::RenderContext&					renderContext,
1733			 TextureRenderer&						textureRenderer,
1734			 tcu::ResultCollector&					results,
1735			 de::Random&							rng,
1736			 deUint32								name,
1737			 const vector<ArrayBuffer<deUint8> >&	data,
1738			 const ImageInfo&						info,
1739			 Verify									verify)
1740{
1741	switch (info.getTarget())
1742	{
1743		case GL_TEXTURE_2D:
1744			renderTexture2D(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
1745			break;
1746
1747		case GL_TEXTURE_3D:
1748			renderTexture3D(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
1749			break;
1750
1751		case GL_TEXTURE_CUBE_MAP:
1752			renderTextureCubemap(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
1753			break;
1754
1755		case GL_TEXTURE_2D_ARRAY:
1756			renderTexture2DArray(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
1757			break;
1758
1759		case GL_RENDERBUFFER:
1760			renderRenderbuffer(testContext, renderContext, results, name, data, info, verify);
1761			break;
1762
1763		default:
1764			DE_ASSERT(false);
1765	}
1766}
1767
1768void logTestImageInfo (TestLog&			log,
1769					   const ImageInfo&	imageInfo)
1770{
1771	log << TestLog::Message << "Target: " << targetToName(imageInfo.getTarget()) << TestLog::EndMessage;
1772	log << TestLog::Message << "Size: " << imageInfo.getSize() << TestLog::EndMessage;
1773	log << TestLog::Message << "Levels: " << getLevelCount(imageInfo) << TestLog::EndMessage;
1774	log << TestLog::Message << "Format: " << formatToName(imageInfo.getFormat()) << TestLog::EndMessage;
1775}
1776
1777void logTestInfo (TestLog&			log,
1778				  const ImageInfo&	srcImageInfo,
1779				  const ImageInfo&	dstImageInfo)
1780{
1781	tcu::ScopedLogSection section(log, "TestCaseInfo", "Test case info");
1782
1783	log << TestLog::Message << "Testing copying from " << targetToName(srcImageInfo.getTarget()) << " to " << targetToName(dstImageInfo.getTarget()) << "." << TestLog::EndMessage;
1784
1785	{
1786		tcu::ScopedLogSection srcSection(log, "Source image info.", "Source image info.");
1787		logTestImageInfo(log, srcImageInfo);
1788	}
1789
1790	{
1791		tcu::ScopedLogSection dstSection(log, "Destination image info.", "Destination image info.");
1792		logTestImageInfo(log, dstImageInfo);
1793	}
1794}
1795
1796class CopyImageTest : public TestCase
1797{
1798public:
1799							CopyImageTest			(Context&			context,
1800													 const ImageInfo&	srcImage,
1801													 const ImageInfo&	dstImage,
1802													 const char*		name,
1803													 const char*		description);
1804
1805							~CopyImageTest			(void);
1806
1807	void					init					(void);
1808	void					deinit					(void);
1809
1810	TestCase::IterateResult	iterate					(void);
1811
1812private:
1813
1814	void					logTestInfoIter			(void);
1815	void					createImagesIter		(void);
1816	void					destroyImagesIter		(void);
1817	void					verifySourceIter		(void);
1818	void					verifyDestinationIter	(void);
1819	void					renderSourceIter		(void);
1820	void					renderDestinationIter	(void);
1821	void					copyImageIter			(void);
1822
1823	typedef void (CopyImageTest::*IterationFunc)(void);
1824
1825	struct Iteration
1826	{
1827		Iteration (int methodCount_, const IterationFunc* methods_)
1828			: methodCount	(methodCount_)
1829			, methods		(methods_)
1830		{
1831		}
1832
1833		int						methodCount;
1834		const IterationFunc*	methods;
1835	};
1836
1837	struct State
1838	{
1839		State (int					seed,
1840			   tcu::TestLog&		log,
1841			   glu::RenderContext&	renderContext)
1842			: rng				(seed)
1843			, results			(log)
1844			, srcImage			(NULL)
1845			, dstImage			(NULL)
1846			, textureRenderer	(renderContext, log, glu::GLSL_VERSION_310_ES, glu::PRECISION_HIGHP)
1847		{
1848		}
1849
1850		~State (void)
1851		{
1852			delete srcImage;
1853			delete dstImage;
1854		}
1855
1856		de::Random						rng;
1857		tcu::ResultCollector			results;
1858		glu::ObjectWrapper*				srcImage;
1859		glu::ObjectWrapper*				dstImage;
1860		TextureRenderer					textureRenderer;
1861
1862		vector<ArrayBuffer<deUint8> >	srcImageLevels;
1863		vector<ArrayBuffer<deUint8> >	dstImageLevels;
1864	};
1865
1866	const ImageInfo	m_srcImageInfo;
1867	const ImageInfo	m_dstImageInfo;
1868
1869	int				m_iteration;
1870	State*			m_state;
1871};
1872
1873CopyImageTest::CopyImageTest (Context&			context,
1874							  const ImageInfo&	srcImage,
1875							  const ImageInfo&	dstImage,
1876							  const char*		name,
1877							  const char*		description)
1878	: TestCase			(context, name, description)
1879	, m_srcImageInfo	(srcImage)
1880	, m_dstImageInfo	(dstImage)
1881
1882	, m_iteration		(0)
1883	, m_state			(NULL)
1884{
1885}
1886
1887CopyImageTest::~CopyImageTest (void)
1888{
1889	deinit();
1890}
1891
1892void checkFormatSupport (glu::ContextInfo& info, deUint32 format, deUint32 target, glu::RenderContext& ctx)
1893{
1894	const bool isES32 = glu::contextSupports(ctx.getType(), glu::ApiType::es(3, 2));
1895
1896	if (glu::isCompressedFormat(format))
1897	{
1898		if (isAstcFormat(glu::mapGLCompressedTexFormat(format)))
1899		{
1900			DE_ASSERT(target != GL_RENDERBUFFER);
1901			if (!info.isExtensionSupported("GL_KHR_texture_compression_astc_hdr") &&
1902				!info.isExtensionSupported("GL_OES_texture_compression_astc"))
1903			{
1904				if (target == GL_TEXTURE_3D)
1905					TCU_THROW(NotSupportedError, "TEXTURE_3D target requires HDR astc support.");
1906				if (!isES32 && !info.isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
1907					TCU_THROW(NotSupportedError, "Compressed astc texture not supported.");
1908			}
1909		}
1910		else
1911		{
1912			if (!info.isCompressedTextureFormatSupported(format))
1913				TCU_THROW(NotSupportedError, "Compressed texture not supported.");
1914		}
1915	}
1916}
1917
1918void CopyImageTest::init (void)
1919{
1920	de::UniquePtr<glu::ContextInfo> ctxInfo(glu::ContextInfo::create(m_context.getRenderContext()));
1921	const bool						isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1922
1923	if (!isES32 && !ctxInfo->isExtensionSupported("GL_EXT_copy_image"))
1924		throw tcu::NotSupportedError("Extension GL_EXT_copy_image not supported.", "", __FILE__, __LINE__);
1925
1926	checkFormatSupport(*ctxInfo, m_srcImageInfo.getFormat(), m_srcImageInfo.getTarget(), m_context.getRenderContext());
1927	checkFormatSupport(*ctxInfo, m_dstImageInfo.getFormat(), m_dstImageInfo.getTarget(), m_context.getRenderContext());
1928
1929	{
1930		SeedBuilder builder;
1931
1932		builder << 903980
1933				<< m_srcImageInfo
1934				<< m_dstImageInfo;
1935
1936		m_state = new State(builder.get(), m_testCtx.getLog(), m_context.getRenderContext());
1937	}
1938}
1939
1940void CopyImageTest::deinit (void)
1941{
1942	delete m_state;
1943	m_state = NULL;
1944}
1945
1946void CopyImageTest::logTestInfoIter (void)
1947{
1948	TestLog& log = m_testCtx.getLog();
1949
1950	logTestInfo(log, m_srcImageInfo, m_dstImageInfo);
1951}
1952
1953void CopyImageTest::createImagesIter (void)
1954{
1955	TestLog&				log						= m_testCtx.getLog();
1956	glu::RenderContext&		renderContext			= m_context.getRenderContext();
1957	const glw::Functions&	gl						= renderContext.getFunctions();
1958	const deUint32			moreRestrictiveFormat	= getMoreRestrictiveFormat(m_srcImageInfo.getFormat(), m_dstImageInfo.getFormat());
1959	de::Random&				rng						= m_state->rng;
1960
1961	DE_ASSERT(!m_state->srcImage);
1962	DE_ASSERT(!m_state->dstImage);
1963
1964	m_state->srcImage = new glu::ObjectWrapper(gl, getObjectTraits(m_srcImageInfo));
1965	m_state->dstImage = new glu::ObjectWrapper(gl, getObjectTraits(m_dstImageInfo));
1966
1967	{
1968		glu::ObjectWrapper&				srcImage				= *m_state->srcImage;
1969		glu::ObjectWrapper&				dstImage				= *m_state->dstImage;
1970
1971		vector<ArrayBuffer<deUint8> >&	srcImageLevels			= m_state->srcImageLevels;
1972		vector<ArrayBuffer<deUint8> >&	dstImageLevels			= m_state->dstImageLevels;
1973
1974		log << TestLog::Message << "Creating source image." << TestLog::EndMessage;
1975		genImage(gl, rng, *srcImage, srcImageLevels, m_srcImageInfo, moreRestrictiveFormat);
1976
1977		log << TestLog::Message << "Creating destination image." << TestLog::EndMessage;
1978		genImage(gl, rng, *dstImage, dstImageLevels, m_dstImageInfo, moreRestrictiveFormat);
1979	}
1980}
1981
1982void CopyImageTest::destroyImagesIter (void)
1983{
1984	TestLog& log = m_testCtx.getLog();
1985
1986	log << TestLog::Message << "Deleting source image. " << TestLog::EndMessage;
1987
1988	delete m_state->srcImage;
1989	m_state->srcImage = NULL;
1990	m_state->srcImageLevels.clear();
1991
1992	log << TestLog::Message << "Deleting destination image. " << TestLog::EndMessage;
1993
1994	delete m_state->dstImage;
1995	m_state->dstImage = NULL;
1996	m_state->dstImageLevels.clear();
1997}
1998
1999void CopyImageTest::verifySourceIter (void)
2000{
2001	TestLog&						log					= m_testCtx.getLog();
2002	const tcu::ScopedLogSection		sourceSection		(log, "Source image verify.", "Source image verify.");
2003
2004	de::Random&						rng					= m_state->rng;
2005	tcu::ResultCollector&			results				= m_state->results;
2006	glu::ObjectWrapper&				srcImage			= *m_state->srcImage;
2007	vector<ArrayBuffer<deUint8> >&	srcImageLevels		= m_state->srcImageLevels;
2008
2009	log << TestLog::Message << "Verifying source image." << TestLog::EndMessage;
2010
2011	render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *srcImage, srcImageLevels, m_srcImageInfo, VERIFY_COMPARE_REFERENCE);
2012}
2013
2014void CopyImageTest::verifyDestinationIter (void)
2015{
2016	TestLog&						log					= m_testCtx.getLog();
2017	const tcu::ScopedLogSection		destinationSection	(log, "Destination image verify.", "Destination image verify.");
2018
2019	de::Random&						rng					= m_state->rng;
2020	tcu::ResultCollector&			results				= m_state->results;
2021	glu::ObjectWrapper&				dstImage			= *m_state->dstImage;
2022	vector<ArrayBuffer<deUint8> >&	dstImageLevels		= m_state->dstImageLevels;
2023
2024	log << TestLog::Message << "Verifying destination image." << TestLog::EndMessage;
2025
2026	render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *dstImage, dstImageLevels, m_dstImageInfo, VERIFY_COMPARE_REFERENCE);
2027}
2028
2029void CopyImageTest::renderSourceIter (void)
2030{
2031	TestLog&						log					= m_testCtx.getLog();
2032	const tcu::ScopedLogSection		sourceSection		(log, "Source image verify.", "Source image verify.");
2033
2034	de::Random&						rng					= m_state->rng;
2035	tcu::ResultCollector&			results				= m_state->results;
2036	glu::ObjectWrapper&				srcImage			= *m_state->srcImage;
2037	vector<ArrayBuffer<deUint8> >&	srcImageLevels		= m_state->srcImageLevels;
2038
2039	log << TestLog::Message << "Verifying source image." << TestLog::EndMessage;
2040
2041	render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *srcImage, srcImageLevels, m_srcImageInfo, VERIFY_NONE);
2042}
2043
2044void CopyImageTest::renderDestinationIter (void)
2045{
2046	TestLog&						log					= m_testCtx.getLog();
2047	const tcu::ScopedLogSection		destinationSection	(log, "Destination image verify.", "Destination image verify.");
2048
2049	de::Random&						rng					= m_state->rng;
2050	tcu::ResultCollector&			results				= m_state->results;
2051	glu::ObjectWrapper&				dstImage			= *m_state->dstImage;
2052	vector<ArrayBuffer<deUint8> >&	dstImageLevels		= m_state->dstImageLevels;
2053
2054	log << TestLog::Message << "Verifying destination image." << TestLog::EndMessage;
2055
2056	render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *dstImage, dstImageLevels, m_dstImageInfo, VERIFY_NONE);
2057}
2058
2059struct Copy
2060{
2061	Copy (const IVec3&	srcPos_,
2062		  int			srcLevel_,
2063
2064		  const IVec3&	dstPos_,
2065		  int			dstLevel_,
2066
2067		  const IVec3&	size_,
2068		  const IVec3&	dstSize_)
2069		: srcPos	(srcPos_)
2070		, srcLevel	(srcLevel_)
2071
2072		, dstPos	(dstPos_)
2073		, dstLevel	(dstLevel_)
2074
2075		, size		(size_)
2076		, dstSize	(dstSize_)
2077	{
2078	}
2079
2080	IVec3	srcPos;
2081	int		srcLevel;
2082	IVec3	dstPos;
2083	int		dstLevel;
2084	IVec3	size;
2085	IVec3	dstSize;	//!< used only for logging
2086};
2087
2088int getLastFullLevel (const ImageInfo& info)
2089{
2090	const int	levelCount		= getLevelCount(info);
2091	const IVec3	blockPixelSize	= getTexelBlockPixelSize(info.getFormat());
2092
2093	for (int level = 0; level < levelCount; level++)
2094	{
2095		const IVec3 levelSize = getLevelSize(info.getTarget(), info.getSize(), level);
2096
2097		if (levelSize.x() < blockPixelSize.x() || levelSize.y() < blockPixelSize.y() || levelSize.z() < blockPixelSize.z())
2098			return level - 1;
2099	}
2100
2101	return levelCount -1;
2102}
2103
2104void generateCopies (vector<Copy>& copies, const ImageInfo& srcInfo, const ImageInfo& dstInfo)
2105{
2106	const deUint32	srcTarget		= srcInfo.getTarget();
2107	const deUint32	dstTarget		= dstInfo.getTarget();
2108
2109	const bool		srcIsTexture	= isTextureTarget(srcInfo.getTarget());
2110	const bool		dstIsTexture	= isTextureTarget(dstInfo.getTarget());
2111
2112	const bool		srcIsCube		= srcTarget == GL_TEXTURE_CUBE_MAP;
2113	const bool		dstIsCube		= dstTarget == GL_TEXTURE_CUBE_MAP;
2114
2115	const IVec3		srcBlockPixelSize		= getTexelBlockPixelSize(srcInfo.getFormat());
2116	const IVec3		dstBlockPixelSize		= getTexelBlockPixelSize(dstInfo.getFormat());
2117
2118	const int levels[] =
2119	{
2120		0, 1, -1
2121	};
2122
2123	for (int levelNdx = 0; levelNdx < (srcIsTexture || dstIsTexture ? DE_LENGTH_OF_ARRAY(levels) : 1); levelNdx++)
2124	{
2125		const int	srcLevel				= (srcIsTexture ? (levels[levelNdx] >= 0 ? levels[levelNdx] : getLastFullLevel(srcInfo)) : 0);
2126		const int	dstLevel				= (dstIsTexture ? (levels[levelNdx] >= 0 ? levels[levelNdx] : getLastFullLevel(dstInfo)) : 0);
2127
2128		const IVec3	srcSize					= getLevelSize(srcInfo.getTarget(), srcInfo.getSize(), srcLevel);
2129		const IVec3	dstSize					= getLevelSize(dstInfo.getTarget(), dstInfo.getSize(), dstLevel);
2130
2131		// \note These are rounded down
2132		const IVec3	srcCompleteBlockSize	= IVec3(srcSize.x() / srcBlockPixelSize.x(), srcSize.y() / srcBlockPixelSize.y(), (srcIsCube ? 6 : srcSize.z() / srcBlockPixelSize.z()));
2133		const IVec3	dstCompleteBlockSize	= IVec3(dstSize.x() / dstBlockPixelSize.x(), dstSize.y() / dstBlockPixelSize.y(), (dstIsCube ? 6 : dstSize.z() / dstBlockPixelSize.z()));
2134
2135		const IVec3	maxCopyBlockSize		= tcu::min(srcCompleteBlockSize, dstCompleteBlockSize);
2136
2137		// \note These are rounded down
2138		const int	copyBlockWidth			= de::max((2 * (maxCopyBlockSize.x() / 4)) - 1, 1);
2139		const int	copyBlockHeight			= de::max((2 * (maxCopyBlockSize.y() / 4)) - 1, 1);
2140		const int	copyBlockDepth			= de::max((2 * (maxCopyBlockSize.z() / 4)) - 1, 1);
2141
2142		// Copy NPOT block to (0,0,0) from other corner on src
2143		{
2144			const IVec3	copyBlockSize	(copyBlockWidth, copyBlockHeight, copyBlockDepth);
2145			const IVec3	srcBlockPos		(srcCompleteBlockSize - copyBlockSize);
2146			const IVec3	dstBlockPos		(0, 0, 0);
2147
2148			const IVec3	srcPos			(srcBlockPos * srcBlockPixelSize);
2149			const IVec3	dstPos			(dstBlockPos * dstBlockPixelSize);
2150			const IVec3 srcCopySize		(copyBlockSize * srcBlockPixelSize);
2151			const IVec3 dstCopySize		(copyBlockSize * dstBlockPixelSize);
2152
2153			copies.push_back(Copy(srcPos, srcLevel, dstPos, dstLevel, srcCopySize, dstCopySize));
2154		}
2155
2156		// Copy NPOT block from (0,0,0) to other corner on dst
2157		{
2158			const IVec3	copyBlockSize	(copyBlockWidth, copyBlockHeight, copyBlockDepth);
2159			const IVec3	srcBlockPos		(0, 0, 0);
2160			const IVec3	dstBlockPos		(dstCompleteBlockSize - copyBlockSize);
2161
2162			const IVec3	srcPos			(srcBlockPos * srcBlockPixelSize);
2163			const IVec3	dstPos			(dstBlockPos * dstBlockPixelSize);
2164			const IVec3 srcCopySize		(copyBlockSize * srcBlockPixelSize);
2165			const IVec3 dstCopySize		(copyBlockSize * dstBlockPixelSize);
2166
2167			copies.push_back(Copy(srcPos, srcLevel, dstPos, dstLevel, srcCopySize, dstCopySize));
2168		}
2169
2170		// Copy NPOT block near the corner with high coordinates
2171		{
2172			const IVec3	copyBlockSize	(copyBlockWidth, copyBlockHeight, copyBlockDepth);
2173			const IVec3	srcBlockPos		(tcu::max((srcCompleteBlockSize / 4) * 4 - copyBlockSize, IVec3(0)));
2174			const IVec3	dstBlockPos		(tcu::max((dstCompleteBlockSize / 4) * 4 - copyBlockSize, IVec3(0)));
2175
2176			const IVec3	srcPos			(srcBlockPos * srcBlockPixelSize);
2177			const IVec3	dstPos			(dstBlockPos * dstBlockPixelSize);
2178			const IVec3 srcCopySize		(copyBlockSize * srcBlockPixelSize);
2179			const IVec3 dstCopySize		(copyBlockSize * dstBlockPixelSize);
2180
2181			copies.push_back(Copy(srcPos, srcLevel, dstPos, dstLevel, srcCopySize, dstCopySize));
2182		}
2183	}
2184}
2185
2186void CopyImageTest::copyImageIter (void)
2187{
2188	TestLog&						log				= m_testCtx.getLog();
2189	const glw::Functions&			gl				= m_context.getRenderContext().getFunctions();
2190	glu::ObjectWrapper&				srcImage		= *m_state->srcImage;
2191	glu::ObjectWrapper&				dstImage		= *m_state->dstImage;
2192
2193	vector<ArrayBuffer<deUint8> >&	srcImageLevels	= m_state->srcImageLevels;
2194	vector<ArrayBuffer<deUint8> >&	dstImageLevels	= m_state->dstImageLevels;
2195	vector<Copy>					copies;
2196
2197	generateCopies(copies, m_srcImageInfo, m_dstImageInfo);
2198
2199	for (int copyNdx = 0; copyNdx < (int)copies.size(); copyNdx++)
2200	{
2201		const Copy& copy = copies[copyNdx];
2202
2203		log	<< TestLog::Message
2204			<< "Copying area with size " << copy.size
2205			<< " from source image position " << copy.srcPos << " and mipmap level " << copy.srcLevel
2206			<< " to destination image position " << copy.dstPos << " and mipmap level " << copy.dstLevel << ". "
2207			<< "Size in destination format is " << copy.dstSize
2208			<< TestLog::EndMessage;
2209
2210		copyImage(gl, *dstImage, dstImageLevels, m_dstImageInfo, copy.dstLevel, copy.dstPos,
2211					  *srcImage, srcImageLevels, m_srcImageInfo, copy.srcLevel, copy.srcPos, copy.size);
2212	}
2213}
2214
2215TestCase::IterateResult CopyImageTest::iterate (void)
2216{
2217	// Note: Returning from iterate() has two side-effects: it touches
2218	// watchdog and calls eglSwapBuffers. For the first it's important
2219	// to keep work per iteration reasonable to avoid
2220	// timeouts. Because of the latter, it's prudent to do more than
2221	// trivial amount of work. Otherwise we'll end up waiting for a
2222	// new buffer in swap, it seems.
2223
2224	// The split below tries to combine trivial work with actually
2225	// expensive rendering iterations without having too much
2226	// rendering in one iteration to avoid timeouts.
2227	const IterationFunc iteration1[] =
2228	{
2229		&CopyImageTest::logTestInfoIter,
2230		&CopyImageTest::createImagesIter,
2231		&CopyImageTest::renderSourceIter
2232	};
2233	const IterationFunc iteration2[] =
2234	{
2235		&CopyImageTest::renderDestinationIter
2236	};
2237	const IterationFunc iteration3[] =
2238	{
2239		&CopyImageTest::copyImageIter,
2240		&CopyImageTest::verifySourceIter
2241	};
2242	const IterationFunc iteration4[] =
2243	{
2244		&CopyImageTest::verifyDestinationIter,
2245		&CopyImageTest::destroyImagesIter
2246	};
2247	const IterationFunc iteration5[] =
2248	{
2249		&CopyImageTest::createImagesIter,
2250		&CopyImageTest::copyImageIter,
2251		&CopyImageTest::verifySourceIter
2252	};
2253	const IterationFunc iteration6[] =
2254	{
2255		&CopyImageTest::verifyDestinationIter,
2256		&CopyImageTest::destroyImagesIter
2257	};
2258	const Iteration iterations[] =
2259	{
2260		Iteration(DE_LENGTH_OF_ARRAY(iteration1), iteration1),
2261		Iteration(DE_LENGTH_OF_ARRAY(iteration2), iteration2),
2262		Iteration(DE_LENGTH_OF_ARRAY(iteration3), iteration3),
2263		Iteration(DE_LENGTH_OF_ARRAY(iteration4), iteration4),
2264		Iteration(DE_LENGTH_OF_ARRAY(iteration5), iteration5),
2265		Iteration(DE_LENGTH_OF_ARRAY(iteration6), iteration6)
2266	};
2267
2268	DE_ASSERT(m_iteration < DE_LENGTH_OF_ARRAY(iterations));
2269	for (int method = 0; method < iterations[m_iteration].methodCount; method++)
2270		(this->*iterations[m_iteration].methods[method])();
2271
2272	m_iteration++;
2273
2274	if (m_iteration < DE_LENGTH_OF_ARRAY(iterations))
2275	{
2276		return CONTINUE;
2277	}
2278	else
2279	{
2280		m_state->results.setTestContextResult(m_testCtx);
2281		return STOP;
2282	}
2283}
2284
2285class CopyImageTests : public TestCaseGroup
2286{
2287public:
2288						CopyImageTests			(Context& context);
2289						~CopyImageTests			(void);
2290
2291	void				init					(void);
2292
2293private:
2294						CopyImageTests			(const CopyImageTests& other);
2295	CopyImageTests&		operator=				(const CopyImageTests& other);
2296};
2297
2298CopyImageTests::CopyImageTests (Context& context)
2299	: TestCaseGroup	(context, "copy_image", "Copy image tests for GL_EXT_copy_image.")
2300{
2301}
2302
2303CopyImageTests::~CopyImageTests (void)
2304{
2305}
2306
2307int smallestCommonMultiple (int a_, int b_)
2308{
2309	int	a		= (a_ > b_ ? a_ : b_);
2310	int	b		= (a_ > b_ ? b_ : a_);
2311	int	result  = 1;
2312
2313	for (int i = b/2; i > 1; i--)
2314	{
2315		while ((a % i) == 0 && (b % i) == 0)
2316		{
2317			result *= i;
2318			a /= i;
2319			b /= i;
2320		}
2321	}
2322
2323	return result * a * b;
2324}
2325
2326IVec3 getTestedSize (deUint32 target, deUint32 format, const IVec3& targetSize)
2327{
2328	const IVec3 texelBlockPixelSize = getTexelBlockPixelSize(format);
2329	const bool	isCube				= target == GL_TEXTURE_CUBE_MAP;
2330	const bool	is3D				= target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
2331
2332	if (isCube)
2333	{
2334		const int	multiplier	= smallestCommonMultiple(texelBlockPixelSize.x(), texelBlockPixelSize.y());
2335		const int	size		= (1 + (targetSize.x() / multiplier)) * multiplier;
2336
2337		return IVec3(size, size, 1);
2338	}
2339	else if (is3D)
2340	{
2341		return (1 + (targetSize / texelBlockPixelSize)) * texelBlockPixelSize;
2342	}
2343	else
2344	{
2345		const int width = (1 + targetSize.x() / texelBlockPixelSize.x()) * texelBlockPixelSize.x();
2346		const int height = ((targetSize.y() / texelBlockPixelSize.y()) - 1) * texelBlockPixelSize.y();
2347
2348		return IVec3(width, height, 1);
2349	}
2350}
2351
2352void addCopyTests (TestCaseGroup* root, deUint32 srcFormat, deUint32 dstFormat)
2353{
2354	const string			groupName	= string(formatToName(srcFormat)) + "_" + formatToName(dstFormat);
2355	TestCaseGroup* const	group		= new TestCaseGroup(root->getContext(), groupName.c_str(), groupName.c_str());
2356
2357	const deUint32 targets[] =
2358	{
2359		GL_TEXTURE_2D,
2360		GL_TEXTURE_3D,
2361		GL_TEXTURE_CUBE_MAP,
2362		GL_TEXTURE_2D_ARRAY,
2363		GL_RENDERBUFFER
2364	};
2365
2366	root->addChild(group);
2367
2368	for (int srcTargetNdx = 0; srcTargetNdx < DE_LENGTH_OF_ARRAY(targets); srcTargetNdx++)
2369	{
2370		const deUint32	srcTarget				= targets[srcTargetNdx];
2371		const bool		srcIs3D					= srcTarget == GL_TEXTURE_2D_ARRAY || srcTarget == GL_TEXTURE_3D;
2372
2373		if (glu::isCompressedFormat(srcFormat) && srcTarget == GL_RENDERBUFFER)
2374			continue;
2375
2376		if (srcTarget == GL_RENDERBUFFER && !isColorRenderable(srcFormat))
2377			continue;
2378
2379		if (glu::isCompressedFormat(srcFormat) && !tcu::isAstcFormat(glu::mapGLCompressedTexFormat(srcFormat)) && srcIs3D)
2380			continue;
2381
2382		for (int dstTargetNdx = 0; dstTargetNdx < DE_LENGTH_OF_ARRAY(targets); dstTargetNdx++)
2383		{
2384			const deUint32	dstTarget				= targets[dstTargetNdx];
2385			const bool		dstIs3D					= dstTarget == GL_TEXTURE_2D_ARRAY || dstTarget == GL_TEXTURE_3D;
2386
2387			if (glu::isCompressedFormat(dstFormat) && dstTarget == GL_RENDERBUFFER)
2388				continue;
2389
2390			if (dstTarget == GL_RENDERBUFFER && !isColorRenderable(dstFormat))
2391				continue;
2392
2393			if (glu::isCompressedFormat(dstFormat) && !tcu::isAstcFormat(glu::mapGLCompressedTexFormat(dstFormat)) && dstIs3D)
2394				continue;
2395
2396			const string	targetTestName	= string(targetToName(srcTarget)) + "_to_" + targetToName(dstTarget);
2397
2398			// Compressed formats require more space to fit all block size combinations.
2399			const bool		isCompressedCase	= glu::isCompressedFormat(srcFormat) || glu::isCompressedFormat(dstFormat);
2400			const IVec3		targetSize			= isCompressedCase ? IVec3(128, 128, 16) : IVec3(64, 64, 8);
2401			const IVec3		srcSize				= getTestedSize(srcTarget, srcFormat, targetSize);
2402			const IVec3		dstSize				= getTestedSize(dstTarget, dstFormat, targetSize);
2403
2404			group->addChild(new CopyImageTest(root->getContext(),
2405											ImageInfo(srcFormat, srcTarget, srcSize),
2406											ImageInfo(dstFormat, dstTarget, dstSize),
2407											targetTestName.c_str(), targetTestName.c_str()));
2408		}
2409	}
2410}
2411
2412void CopyImageTests::init (void)
2413{
2414	TestCaseGroup* const	nonCompressedGroup	= new TestCaseGroup(m_context, "non_compressed", "Test copying between textures.");
2415	TestCaseGroup* const	compressedGroup		= new TestCaseGroup(m_context, "compressed", "Test copying between compressed textures.");
2416	TestCaseGroup* const	mixedGroup			= new TestCaseGroup(m_context, "mixed", "Test copying between compressed and non-compressed textures.");
2417
2418	addChild(nonCompressedGroup);
2419	addChild(compressedGroup);
2420	addChild(mixedGroup);
2421
2422	map<ViewClass, vector<deUint32> >							textureFormatViewClasses;
2423	map<ViewClass, vector<deUint32> >							compressedTextureFormatViewClasses;
2424	map<ViewClass, pair<vector<deUint32>, vector<deUint32> > >	mixedViewClasses;
2425
2426	// Texture view classes
2427	textureFormatViewClasses[VIEWCLASS_128_BITS]		= vector<deUint32>();
2428	textureFormatViewClasses[VIEWCLASS_96_BITS]			= vector<deUint32>();
2429	textureFormatViewClasses[VIEWCLASS_64_BITS]			= vector<deUint32>();
2430	textureFormatViewClasses[VIEWCLASS_48_BITS]			= vector<deUint32>();
2431	textureFormatViewClasses[VIEWCLASS_32_BITS]			= vector<deUint32>();
2432	textureFormatViewClasses[VIEWCLASS_24_BITS]			= vector<deUint32>();
2433	textureFormatViewClasses[VIEWCLASS_16_BITS]			= vector<deUint32>();
2434	textureFormatViewClasses[VIEWCLASS_8_BITS]			= vector<deUint32>();
2435
2436	// 128bit / VIEWCLASS_128_BITS
2437	textureFormatViewClasses[VIEWCLASS_128_BITS].push_back(GL_RGBA32F);
2438	textureFormatViewClasses[VIEWCLASS_128_BITS].push_back(GL_RGBA32I);
2439	textureFormatViewClasses[VIEWCLASS_128_BITS].push_back(GL_RGBA32UI);
2440
2441	// 96bit / VIEWCLASS_96_BITS
2442	textureFormatViewClasses[VIEWCLASS_96_BITS].push_back(GL_RGB32F);
2443	textureFormatViewClasses[VIEWCLASS_96_BITS].push_back(GL_RGB32I);
2444	textureFormatViewClasses[VIEWCLASS_96_BITS].push_back(GL_RGB32UI);
2445
2446	// 64bit / VIEWCLASS_64_BITS
2447	textureFormatViewClasses[VIEWCLASS_64_BITS].push_back(GL_RG32F);
2448	textureFormatViewClasses[VIEWCLASS_64_BITS].push_back(GL_RG32I);
2449	textureFormatViewClasses[VIEWCLASS_64_BITS].push_back(GL_RG32UI);
2450
2451	textureFormatViewClasses[VIEWCLASS_64_BITS].push_back(GL_RGBA16F);
2452	textureFormatViewClasses[VIEWCLASS_64_BITS].push_back(GL_RGBA16I);
2453	textureFormatViewClasses[VIEWCLASS_64_BITS].push_back(GL_RGBA16UI);
2454
2455	// 48bit / VIEWCLASS_48_BITS
2456	textureFormatViewClasses[VIEWCLASS_48_BITS].push_back(GL_RGB16F);
2457	textureFormatViewClasses[VIEWCLASS_48_BITS].push_back(GL_RGB16I);
2458	textureFormatViewClasses[VIEWCLASS_48_BITS].push_back(GL_RGB16UI);
2459
2460	// 32bit / VIEWCLASS_32_BITS
2461	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_R32F);
2462	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_R32I);
2463	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_R32UI);
2464
2465	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RG16F);
2466	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RG16I);
2467	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RG16UI);
2468
2469	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RGBA8);
2470	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RGBA8I);
2471	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RGBA8UI);
2472
2473	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_R11F_G11F_B10F);
2474	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RGB10_A2UI);
2475	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RGB10_A2);
2476	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RGBA8_SNORM);
2477	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_SRGB8_ALPHA8);
2478	textureFormatViewClasses[VIEWCLASS_32_BITS].push_back(GL_RGB9_E5);
2479
2480	// 24bit / VIEWCLASS_24_BITS
2481	textureFormatViewClasses[VIEWCLASS_24_BITS].push_back(GL_RGB8);
2482	textureFormatViewClasses[VIEWCLASS_24_BITS].push_back(GL_RGB8I);
2483	textureFormatViewClasses[VIEWCLASS_24_BITS].push_back(GL_RGB8UI);
2484	textureFormatViewClasses[VIEWCLASS_24_BITS].push_back(GL_RGB8_SNORM);
2485	textureFormatViewClasses[VIEWCLASS_24_BITS].push_back(GL_SRGB8);
2486
2487	// 16bit / VIEWCLASS_16_BITS
2488	textureFormatViewClasses[VIEWCLASS_16_BITS].push_back(GL_R16F);
2489	textureFormatViewClasses[VIEWCLASS_16_BITS].push_back(GL_R16I);
2490	textureFormatViewClasses[VIEWCLASS_16_BITS].push_back(GL_R16UI);
2491
2492	textureFormatViewClasses[VIEWCLASS_16_BITS].push_back(GL_RG8);
2493	textureFormatViewClasses[VIEWCLASS_16_BITS].push_back(GL_RG8I);
2494	textureFormatViewClasses[VIEWCLASS_16_BITS].push_back(GL_RG8UI);
2495	textureFormatViewClasses[VIEWCLASS_16_BITS].push_back(GL_RG8_SNORM);
2496
2497	// 8bit / VIEWCLASS_8_BITS
2498	textureFormatViewClasses[VIEWCLASS_8_BITS].push_back(GL_R8);
2499	textureFormatViewClasses[VIEWCLASS_8_BITS].push_back(GL_R8I);
2500	textureFormatViewClasses[VIEWCLASS_8_BITS].push_back(GL_R8UI);
2501	textureFormatViewClasses[VIEWCLASS_8_BITS].push_back(GL_R8_SNORM);
2502
2503	// Compressed texture view classes
2504	compressedTextureFormatViewClasses[VIEWCLASS_EAC_R11]			= vector<deUint32>();
2505	compressedTextureFormatViewClasses[VIEWCLASS_EAC_RG11]			= vector<deUint32>();
2506	compressedTextureFormatViewClasses[VIEWCLASS_ETC2_RGB]			= vector<deUint32>();
2507	compressedTextureFormatViewClasses[VIEWCLASS_ETC2_RGBA]			= vector<deUint32>();
2508	compressedTextureFormatViewClasses[VIEWCLASS_ETC2_EAC_RGBA]		= vector<deUint32>();
2509	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_4x4_RGBA]		= vector<deUint32>();
2510	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_5x4_RGBA]		= vector<deUint32>();
2511	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_5x5_RGBA]		= vector<deUint32>();
2512	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_6x5_RGBA]		= vector<deUint32>();
2513	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_6x6_RGBA]		= vector<deUint32>();
2514	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_8x5_RGBA]		= vector<deUint32>();
2515	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_8x6_RGBA]		= vector<deUint32>();
2516	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_8x8_RGBA]		= vector<deUint32>();
2517	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x5_RGBA]	= vector<deUint32>();
2518	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x6_RGBA]	= vector<deUint32>();
2519	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x8_RGBA]	= vector<deUint32>();
2520	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x10_RGBA]	= vector<deUint32>();
2521	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_12x10_RGBA]	= vector<deUint32>();
2522	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_12x12_RGBA]	= vector<deUint32>();
2523
2524	// VIEWCLASS_EAC_R11
2525	compressedTextureFormatViewClasses[VIEWCLASS_EAC_R11].push_back(GL_COMPRESSED_R11_EAC);
2526	compressedTextureFormatViewClasses[VIEWCLASS_EAC_R11].push_back(GL_COMPRESSED_SIGNED_R11_EAC);
2527
2528	// VIEWCLASS_EAC_RG11
2529	compressedTextureFormatViewClasses[VIEWCLASS_EAC_RG11].push_back(GL_COMPRESSED_RG11_EAC);
2530	compressedTextureFormatViewClasses[VIEWCLASS_EAC_RG11].push_back(GL_COMPRESSED_SIGNED_RG11_EAC);
2531
2532	// VIEWCLASS_ETC2_RGB
2533	compressedTextureFormatViewClasses[VIEWCLASS_ETC2_RGB].push_back(GL_COMPRESSED_RGB8_ETC2);
2534	compressedTextureFormatViewClasses[VIEWCLASS_ETC2_RGB].push_back(GL_COMPRESSED_SRGB8_ETC2);
2535
2536	// VIEWCLASS_ETC2_RGBA
2537	compressedTextureFormatViewClasses[VIEWCLASS_ETC2_RGBA].push_back(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
2538	compressedTextureFormatViewClasses[VIEWCLASS_ETC2_RGBA].push_back(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
2539
2540	// VIEWCLASS_ETC2_EAC_RGBA
2541	compressedTextureFormatViewClasses[VIEWCLASS_ETC2_EAC_RGBA].push_back(GL_COMPRESSED_RGBA8_ETC2_EAC);
2542	compressedTextureFormatViewClasses[VIEWCLASS_ETC2_EAC_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
2543
2544	// VIEWCLASS_ASTC_4x4_RGBA
2545	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_4x4_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_4x4);
2546	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_4x4_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4);
2547
2548	// VIEWCLASS_ASTC_5x4_RGBA
2549	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_5x4_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_5x4);
2550	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_5x4_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4);
2551
2552	// VIEWCLASS_ASTC_5x5_RGBA
2553	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_5x5_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_5x5);
2554	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_5x5_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5);
2555
2556	// VIEWCLASS_ASTC_6x5_RGBA
2557	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_6x5_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_6x5);
2558	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_6x5_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5);
2559
2560	// VIEWCLASS_ASTC_6x6_RGBA
2561	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_6x6_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_6x6);
2562	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_6x6_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6);
2563
2564	// VIEWCLASS_ASTC_8x5_RGBA
2565	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_8x5_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_8x5);
2566	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_8x5_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5);
2567
2568	// VIEWCLASS_ASTC_8x6_RGBA
2569	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_8x6_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_8x6);
2570	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_8x6_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6);
2571
2572	// VIEWCLASS_ASTC_8x8_RGBA
2573	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_8x8_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_8x8);
2574	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_8x8_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8);
2575
2576	// VIEWCLASS_ASTC_10x5_RGBA
2577	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x5_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_10x5);
2578	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x5_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5);
2579
2580	// VIEWCLASS_ASTC_10x6_RGBA
2581	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x6_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_10x6);
2582	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x6_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6);
2583
2584	// VIEWCLASS_ASTC_10x8_RGBA
2585	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x8_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_10x8);
2586	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x8_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8);
2587
2588	// VIEWCLASS_ASTC_10x10_RGBA
2589	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x10_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_10x10);
2590	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_10x10_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10);
2591
2592	// VIEWCLASS_ASTC_12x10_RGBA
2593	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_12x10_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_12x10);
2594	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_12x10_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10);
2595
2596	// VIEWCLASS_ASTC_12x12_RGBA
2597	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_12x12_RGBA].push_back(GL_COMPRESSED_RGBA_ASTC_12x12);
2598	compressedTextureFormatViewClasses[VIEWCLASS_ASTC_12x12_RGBA].push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12);
2599
2600	// Mixed view classes
2601	mixedViewClasses[VIEWCLASS_128_BITS] = pair<vector<deUint32>, vector<deUint32> >();
2602	mixedViewClasses[VIEWCLASS_64_BITS] = pair<vector<deUint32>, vector<deUint32> >();
2603
2604	// 128 bits
2605
2606	// Non compressed
2607	mixedViewClasses[VIEWCLASS_128_BITS].first.push_back(GL_RGBA32F);
2608	mixedViewClasses[VIEWCLASS_128_BITS].first.push_back(GL_RGBA32UI);
2609	mixedViewClasses[VIEWCLASS_128_BITS].first.push_back(GL_RGBA32I);
2610
2611	// Compressed
2612	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA8_ETC2_EAC);
2613	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
2614	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RG11_EAC);
2615	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SIGNED_RG11_EAC);
2616	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_4x4);
2617	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_5x4);
2618	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_5x5);
2619	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_6x5);
2620	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_6x6);
2621	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_8x5);
2622	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_8x6);
2623	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_8x8);
2624	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_10x5);
2625	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_10x6);
2626	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_10x8);
2627	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_10x10);
2628	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_12x10);
2629	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_RGBA_ASTC_12x12);
2630	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4);
2631	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4);
2632	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5);
2633	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5);
2634	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6);
2635	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5);
2636	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6);
2637	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8);
2638	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5);
2639	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6);
2640	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8);
2641	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10);
2642	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10);
2643	mixedViewClasses[VIEWCLASS_128_BITS].second.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12);
2644
2645	// 64 bits
2646
2647	// Non compressed
2648	mixedViewClasses[VIEWCLASS_64_BITS].first.push_back(GL_RGBA16F);
2649	mixedViewClasses[VIEWCLASS_64_BITS].first.push_back(GL_RGBA16UI);
2650	mixedViewClasses[VIEWCLASS_64_BITS].first.push_back(GL_RGBA16I);
2651
2652	mixedViewClasses[VIEWCLASS_64_BITS].first.push_back(GL_RG32F);
2653	mixedViewClasses[VIEWCLASS_64_BITS].first.push_back(GL_RG32UI);
2654	mixedViewClasses[VIEWCLASS_64_BITS].first.push_back(GL_RG32I);
2655
2656	// Compressed
2657	mixedViewClasses[VIEWCLASS_64_BITS].second.push_back(GL_COMPRESSED_R11_EAC);
2658	mixedViewClasses[VIEWCLASS_64_BITS].second.push_back(GL_COMPRESSED_SIGNED_R11_EAC);
2659
2660	for (map<ViewClass, vector<deUint32> >::const_iterator viewClassIter = textureFormatViewClasses.begin(); viewClassIter != textureFormatViewClasses.end(); ++viewClassIter)
2661	{
2662		const vector<deUint32>&	formats		= viewClassIter->second;
2663		const ViewClass			viewClass	= viewClassIter->first;
2664		TestCaseGroup* const	viewGroup	= new TestCaseGroup(m_context, viewClassToName(viewClass), viewClassToName(viewClass));
2665
2666		nonCompressedGroup->addChild(viewGroup);
2667
2668		for (int srcFormatNdx = 0; srcFormatNdx < (int)formats.size(); srcFormatNdx++)
2669		for (int dstFormatNdx = 0; dstFormatNdx < (int)formats.size(); dstFormatNdx++)
2670		{
2671			const deUint32 srcFormat = formats[srcFormatNdx];
2672			const deUint32 dstFormat = formats[dstFormatNdx];
2673
2674			if (srcFormat != dstFormat && isFloatFormat(srcFormat) && isFloatFormat(dstFormat))
2675				continue;
2676
2677			addCopyTests(viewGroup, srcFormat, dstFormat);
2678		}
2679	}
2680
2681	for (map<ViewClass, vector<deUint32> >::const_iterator viewClassIter = compressedTextureFormatViewClasses.begin(); viewClassIter != compressedTextureFormatViewClasses.end(); ++viewClassIter)
2682	{
2683		const vector<deUint32>&	formats		= viewClassIter->second;
2684		const ViewClass			viewClass	= viewClassIter->first;
2685		TestCaseGroup* const	viewGroup	= new TestCaseGroup(m_context, viewClassToName(viewClass), viewClassToName(viewClass));
2686
2687		compressedGroup->addChild(viewGroup);
2688
2689		for (int srcFormatNdx = 0; srcFormatNdx < (int)formats.size(); srcFormatNdx++)
2690		for (int dstFormatNdx = 0; dstFormatNdx < (int)formats.size(); dstFormatNdx++)
2691		{
2692			const deUint32 srcFormat = formats[srcFormatNdx];
2693			const deUint32 dstFormat = formats[dstFormatNdx];
2694
2695			if (srcFormat != dstFormat && isFloatFormat(srcFormat) && isFloatFormat(dstFormat))
2696				continue;
2697
2698			addCopyTests(viewGroup, srcFormat, dstFormat);
2699		}
2700	}
2701
2702	for (map<ViewClass, pair<vector<deUint32>, vector<deUint32> > >::const_iterator iter = mixedViewClasses.begin(); iter != mixedViewClasses.end(); ++iter)
2703	{
2704		const ViewClass			viewClass				= iter->first;
2705		const string			viewClassName			= string(viewClassToName(viewClass)) + "_mixed";
2706		TestCaseGroup* const	viewGroup				= new TestCaseGroup(m_context, viewClassName.c_str(), viewClassName.c_str());
2707
2708		const vector<deUint32>	nonCompressedFormats	= iter->second.first;
2709		const vector<deUint32>	compressedFormats		= iter->second.second;
2710
2711		mixedGroup->addChild(viewGroup);
2712
2713		for (int srcFormatNdx = 0; srcFormatNdx < (int)nonCompressedFormats.size(); srcFormatNdx++)
2714		for (int dstFormatNdx = 0; dstFormatNdx < (int)compressedFormats.size(); dstFormatNdx++)
2715		{
2716			const deUint32 srcFormat = nonCompressedFormats[srcFormatNdx];
2717			const deUint32 dstFormat = compressedFormats[dstFormatNdx];
2718
2719			if (srcFormat != dstFormat && isFloatFormat(srcFormat) && isFloatFormat(dstFormat))
2720				continue;
2721
2722			addCopyTests(viewGroup, srcFormat, dstFormat);
2723			addCopyTests(viewGroup, dstFormat, srcFormat);
2724		}
2725	}
2726}
2727
2728} // anonymous
2729
2730TestCaseGroup* createCopyImageTests (Context& context)
2731{
2732	return new CopyImageTests(context);
2733}
2734
2735} // Functional
2736} // gles31
2737} // deqp
2738