1/*-------------------------------------------------------------------------
2* OpenGL Conformance Test Suite
3* -----------------------------
4*
5* Copyright (c) 2020 The Khronos Group Inc.
6* Copyright (c) 2020 Intel Corporation
7*
8* Licensed under the Apache License, Version 2.0 (the "License");
9* you may not use this file except in compliance with the License.
10* You may obtain a copy of the License at
11*
12*      http://www.apache.org/licenses/LICENSE-2.0
13*
14* Unless required by applicable law or agreed to in writing, software
15* distributed under the License is distributed on an "AS IS" BASIS,
16* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17* See the License for the specific language governing permissions and
18* limitations under the License.
19*
20*/ /*!
21* \file  glcPixelStorageModesTests.cpp
22* \brief Conformance tests for usage of pixel storage modes.
23*/ /*-------------------------------------------------------------------*/
24
25#include "stdlib.h"
26#include "tcuRenderTarget.hpp"
27#include "tcuSurface.hpp"
28#include "tcuTextureUtil.hpp"
29#include "tcuTestCase.hpp"
30#include "tcuTestLog.hpp"
31#include "tcuDefs.hpp"
32#include "tcuFloat.hpp"
33#include "tcuStringTemplate.hpp"
34#include "gluRenderContext.hpp"
35#include "gluShaderProgram.hpp"
36#include "gluShaderUtil.hpp"
37#include "gluContextInfo.hpp"
38#include "gluObjectWrapper.hpp"
39#include "gluCallLogWrapper.hpp"
40#include "gluPixelTransfer.hpp"
41#include "gluTexture.hpp"
42#include "gluTextureUtil.hpp"
43#include "gluDrawUtil.hpp"
44#include "gluDefs.hpp"
45#include "sglrGLContext.hpp"
46#include "sglrContextWrapper.hpp"
47#include "sglrContextUtil.hpp"
48#include "glwFunctions.hpp"
49#include "glwEnums.hpp"
50#include "deStringUtil.hpp"
51#include "deUniquePtr.hpp"
52#include "glsTextureTestUtil.hpp"
53#include "glcPixelStorageModesTests.hpp"
54
55#include <algorithm>
56
57namespace glcts
58{
59
60static const char* const vs_template_src =
61	"${GLSL_VERSION}\n"
62	"in highp vec4 pos;\n"
63	"out highp ${TEXCOORDS_TYPE} texcoords;\n"
64	"${LAYER}\n"
65	"void main (void)\n"
66	"{\n"
67	"	 texcoords = ${TEXCOORDS};\n"
68	"	 gl_Position = pos;\n"
69	"}\n";
70
71static const char* const fs_template_src =
72	"${GLSL_VERSION}\n"
73	"precision highp float;\n"
74	"precision highp int;\n"
75	"out vec4 fragColour;\n"
76	"in ${TEXCOORDS_TYPE} texcoords;\n"
77	"uniform highp ${SAMPLER_TYPE} sampler;\n"
78	"uniform ${COL_TYPE} refcolour;\n"
79	"void main (void)\n"
80	"{\n"
81	"	 ${COL_TYPE} colour = texelFetch(sampler, i${TEXCOORDS_TYPE}(texcoords), 0);\n"
82	"	 if (${CONDITION})\n"
83	"		 fragColour = vec4(0.0, 1.0, 0.0, 1.0);\n"
84	"	 else\n"
85	"		 fragColour = vec4(colour);\n"
86	"}\n";
87
88double getEps(deUint32 internalFormat)
89{
90	double eps = 0.0;
91	switch (internalFormat)
92	{
93	case GL_RGBA4:
94		eps = 1.0 / (double)(1 << 4);
95		break;
96	case GL_RGB565:
97	case GL_RGB5_A1:
98	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
99		eps = 1.0 / (double)(1 << 5);
100		break;
101	case GL_R8:
102	case GL_R8_SNORM:
103	case GL_RG8:
104	case GL_RG8_SNORM:
105	case GL_RGB8:
106	case GL_SRGB8:
107	case GL_RGB8_SNORM:
108	case GL_RGBA8:
109	case GL_SRGB8_ALPHA8:
110	case GL_RGBA8_SNORM:
111		eps = 1.0 / (double)(1 << 8);
112		break;
113	case GL_RGB9_E5:
114		eps = 1.0 / (double)(1 << 9);
115		break;
116	case GL_R11F_G11F_B10F:
117	case GL_RGB10_A2:
118		eps = 1.0 / (double)(1 << 10);
119		break;
120	case GL_R16F:
121	case GL_RG16F:
122	case GL_RGB16F:
123	case GL_RGBA16F:
124	case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
125		eps = 1.0 / (double)(1 << 16);
126		break;
127	case GL_R32F:
128	case GL_RG32F:
129	case GL_RGB32F:
130	case GL_RGBA32F:
131		eps = 1.0 / (double)(1 << 31);
132		break;
133	default:
134		TCU_FAIL("Invalid internal format");
135	}
136
137	return std::max(0.01, eps);
138}
139
140bool inrange(int x, int left, int right)
141{
142	return (x >= left && x < right);
143}
144
145class TexImageUtils
146{
147public:
148	TexImageUtils(deUint32 internalFormat,
149				  int cuboid_w, int cuboid_h, int cuboid_d,
150				  int subcuboid_x0, int subcuboid_y0, int subcuboid_z0,
151				  int subcuboid_w, int subcuboid_h, int subcuboid_d,
152				  glu::GLSLVersion glsl_version);
153	~TexImageUtils (void);
154protected:
155	void writePixel(glw::GLubyte *p, glw::GLdouble col);
156	void writeChannel(glw::GLubyte *p, int channel, glw::GLdouble col);
157	template <typename T>
158	void writeToUnsignedChannel(glw::GLubyte *p, int channel, glw::GLdouble col);
159	template <typename T>
160	void writeToSignedChannel(glw::GLubyte *p, int channel, glw::GLdouble col);
161	void writeToFloatChannel(glw::GLubyte *p, int channel, glw::GLdouble col);
162	void writeToHalfFloatChannel(glw::GLubyte *p, int channel, glw::GLdouble col);
163	template <typename T,
164				 unsigned int size_1, unsigned int size_2, unsigned int size_3,
165				 unsigned int off_1, unsigned int off_2, unsigned int off_3>
166	void write3Channel(glw::GLubyte *p, int channel, glw::GLdouble col);
167	template <typename T,
168				 unsigned int size_1, unsigned int size_2,
169				 unsigned int size_3, unsigned int size_4,
170				 unsigned int off_1, unsigned int off_2,
171				 unsigned int off_3, unsigned int off_4>
172	void write4Channel(glw::GLubyte *p, int channel, glw::GLdouble col);
173	void write11F_11F_10F_Channel(glw::GLubyte *p, int channel, glw::GLdouble col);
174	void setRefcolour (glu::CallLogWrapper gl, glw::GLdouble col);
175	template <typename T>
176	void setUnsignedRefcolour(glu::CallLogWrapper gl, glw::GLdouble col);
177	template <typename T>
178	void setSignedRefcolour(glu::CallLogWrapper gl, glw::GLdouble col);
179	void setRGB10A2Refcolour (glu::CallLogWrapper gl, glw::GLdouble col);
180	bool verify(tcu::Surface dst, tcu::Surface *errMask);
181
182	glw::GLubyte *m_src_data;
183	deUint32 tex;
184	glu::ShaderProgram* prog;
185
186	deUint32 m_internalFormat;
187	deUint32 m_format;
188	deUint32 m_type;
189	int m_pixelsize;
190	int m_num_channels;
191	int m_cuboid_w;
192	int m_cuboid_h;
193	int m_cuboid_d;
194	int m_subcuboid_x0;
195	int m_subcuboid_y0;
196	int m_subcuboid_z0;
197	int m_subcuboid_w;
198	int m_subcuboid_h;
199	int m_subcuboid_d;
200
201	glu::GLSLVersion m_glsl_version;
202};
203
204TexImageUtils::TexImageUtils (deUint32 internalFormat,
205							  int cuboid_w,
206							  int cuboid_h,
207							  int cuboid_d,
208							  int subcuboid_x0,
209							  int subcuboid_y0,
210							  int subcuboid_z0,
211							  int subcuboid_w,
212							  int subcuboid_h,
213							  int subcuboid_d,
214							  glu::GLSLVersion glsl_version)
215	: m_src_data(0)
216	, tex(0)
217	, prog(0)
218	, m_internalFormat(internalFormat)
219	, m_format(glu::getTransferFormat(glu::mapGLInternalFormat(internalFormat)).format)
220	, m_type(glu::getTransferFormat(glu::mapGLInternalFormat(internalFormat)).dataType)
221	, m_pixelsize(tcu::getPixelSize(glu::mapGLInternalFormat(internalFormat)))
222	, m_num_channels(tcu::getNumUsedChannels(glu::mapGLInternalFormat(internalFormat).order))
223	, m_cuboid_w(cuboid_w)
224	, m_cuboid_h(cuboid_h)
225	, m_cuboid_d(cuboid_d)
226	, m_subcuboid_x0(subcuboid_x0)
227	, m_subcuboid_y0(subcuboid_y0)
228	, m_subcuboid_z0(subcuboid_z0)
229	, m_subcuboid_w(subcuboid_w)
230	, m_subcuboid_h(subcuboid_h)
231	, m_subcuboid_d(subcuboid_d)
232	, m_glsl_version(glsl_version)
233{
234}
235
236TexImageUtils::~TexImageUtils (void)
237{
238}
239
240void TexImageUtils::writePixel(glw::GLubyte *p, glw::GLdouble col)
241{
242	for (int ch = 0; ch < m_num_channels; ch++)
243		writeChannel(p, ch, (ch == 3) ? 1.0 : col);
244}
245
246void TexImageUtils::writeChannel(glw::GLubyte *p, int channel, glw::GLdouble col)
247{
248	switch (m_type)
249	{
250	case GL_UNSIGNED_BYTE:
251		writeToUnsignedChannel<glw::GLubyte>(p, channel, col);
252		break;
253	case GL_BYTE:
254		writeToSignedChannel<glw::GLbyte>(p, channel, col);
255		break;
256	case GL_UNSIGNED_SHORT:
257		writeToUnsignedChannel<glw::GLushort>(p, channel, col);
258		break;
259	case GL_UNSIGNED_SHORT_5_6_5:
260		write3Channel<glw::GLushort, 5, 6, 5, 11, 5, 0>(p, channel, col);
261		break;
262	case GL_SHORT:
263		writeToSignedChannel<glw::GLshort>(p, channel, col);
264		break;
265	case GL_UNSIGNED_INT:
266		writeToUnsignedChannel<glw::GLuint>(p, channel, col);
267		break;
268	case GL_UNSIGNED_INT_2_10_10_10_REV:
269		write4Channel<glw::GLuint, 2, 10, 10, 10, 30, 20, 10, 0>(p, 3 - channel, col);
270		break;
271	case GL_UNSIGNED_INT_10F_11F_11F_REV:
272		write11F_11F_10F_Channel(p, channel, col);
273		break;
274	case GL_UNSIGNED_SHORT_4_4_4_4:
275		write4Channel<glw::GLushort, 4, 4, 4, 4, 12, 8, 4, 0>(p, channel, col);
276		break;
277	case GL_UNSIGNED_SHORT_5_5_5_1:
278		write4Channel<glw::GLushort, 5, 5, 5, 1, 11, 6, 1, 0>(p, channel, col);
279		break;
280	case GL_INT:
281		writeToSignedChannel<glw::GLint>(p, channel, col);
282		break;
283	case GL_HALF_FLOAT:
284		writeToHalfFloatChannel(p, channel, col);
285		break;
286	case GL_FLOAT:
287		writeToFloatChannel(p, channel, col);
288		break;
289	default:
290		TCU_FAIL("Invalid type");
291	}
292}
293
294template <typename T>
295void TexImageUtils::writeToUnsignedChannel(glw::GLubyte *p, int channel, glw::GLdouble col)
296{
297	static const T max = -1;
298
299	const glw::GLdouble d_max = (glw::GLdouble)max;
300	const glw::GLdouble d_value = col * d_max;
301	const T t_value = (T)d_value;
302
303	T* ptr = (T*)p;
304
305	ptr[channel] = t_value;
306}
307
308template <typename T>
309void TexImageUtils::writeToSignedChannel(glw::GLubyte *p, int channel, glw::GLdouble col)
310{
311	static const T max = (T)((1u << (sizeof(T) * 8u - 1u)) - 1u);
312
313	const glw::GLdouble d_max = (glw::GLdouble)max;
314	const glw::GLdouble d_value = col * d_max;
315	const T t_value = (T)d_value;
316
317	T* ptr = (T*)p;
318
319	ptr[channel] = t_value;
320}
321
322void TexImageUtils::writeToFloatChannel(glw::GLubyte *p, int channel, glw::GLdouble col)
323{
324	const glw::GLfloat t_value = (glw::GLfloat)col;
325
326	glw::GLfloat *ptr = (glw::GLfloat*)p;
327
328	ptr[channel] = t_value;
329}
330
331void TexImageUtils::writeToHalfFloatChannel(glw::GLubyte *p, int channel, glw::GLdouble col)
332{
333	deUint16* ptr = (deUint16*)p;
334
335	tcu::Float16 val(col);
336
337	ptr[channel] = val.bits();
338}
339
340template <typename T,
341			 unsigned int size_1, unsigned int size_2, unsigned int size_3,
342			 unsigned int off_1, unsigned int off_2, unsigned int off_3>
343void TexImageUtils::write3Channel(glw::GLubyte *p, int channel, glw::GLdouble col)
344{
345	T mask = 0;
346	T max = 0;
347	T off = 0;
348	T* ptr = (T*)p;
349	T result = 0;
350
351	const T max_1 = (1 << size_1) - 1;
352	const T max_2 = (1 << size_2) - 1;
353	const T max_3 = (1 << size_3) - 1;
354
355	switch (channel)
356	{
357	case 0:
358		mask = max_1;
359		max  = max_1;
360		off  = off_1;
361		break;
362	case 1:
363		mask = max_2;
364		max  = max_2;
365		off  = off_2;
366		break;
367	case 2:
368		mask = max_3;
369		max  = max_3;
370		off  = off_3;
371		break;
372	default:
373		TCU_FAIL("Invalid channel");
374		break;
375	}
376
377	const glw::GLdouble d_max	 = (glw::GLdouble)max;
378	const glw::GLdouble d_value  = col * d_max;
379	const T t_value = (T)d_value;
380
381	result = (T)((t_value & mask) << off);
382
383	*ptr |= result;
384}
385
386template <typename T,
387			 unsigned int size_1, unsigned int size_2,
388			 unsigned int size_3, unsigned int size_4,
389			 unsigned int off_1, unsigned int off_2,
390			 unsigned int off_3, unsigned int off_4>
391void TexImageUtils::write4Channel(glw::GLubyte *p, int channel, glw::GLdouble col)
392{
393	T mask	 = 0;
394	T max	 = 0;
395	T off	 = 0;
396	T* ptr	 = (T*)p;
397	T result = 0;
398
399	T max_1 = (1 << size_1) - 1;
400	T max_2 = (1 << size_2) - 1;
401	T max_3 = (1 << size_3) - 1;
402	T max_4 = (1 << size_4) - 1;
403
404	switch (channel)
405	{
406	case 0:
407		mask = max_1;
408		max  = max_1;
409		off  = off_1;
410		break;
411	case 1:
412		mask = max_2;
413		max  = max_2;
414		off  = off_2;
415		break;
416	case 2:
417		mask = max_3;
418		max  = max_3;
419		off  = off_3;
420		break;
421	case 3:
422		mask = max_4;
423		max  = max_4;
424		off  = off_4;
425		break;
426	default:
427		TCU_FAIL("Invalid channel");
428		break;
429	}
430
431	const glw::GLdouble d_max	 = (glw::GLdouble)max;
432	const glw::GLdouble d_value  = col * d_max;
433	const T t_value = (T)d_value;
434
435	result = (T)((t_value & mask) << off);
436
437	*ptr |= result;
438}
439
440void TexImageUtils::write11F_11F_10F_Channel(glw::GLubyte *p, int channel, glw::GLdouble col)
441{
442	deUint32* ptr = (deUint32*)p;
443
444	switch (channel)
445	{
446	case 0:
447	{
448		tcu::Float<deUint32, 5, 6, 15, tcu::FLOAT_SUPPORT_DENORM> val(col);
449		deUint32 bits = val.bits();
450
451		*ptr |= bits;
452	}
453	break;
454	case 1:
455	{
456		tcu::Float<deUint32, 5, 6, 15, tcu::FLOAT_SUPPORT_DENORM> val(col);
457		deUint32 bits = val.bits();
458
459		*ptr |= (bits << 11);
460	}
461	break;
462	case 2:
463	{
464		tcu::Float<deUint32, 5, 5, 15, tcu::FLOAT_SUPPORT_DENORM> val(col);
465		deUint32 bits = val.bits();
466
467		*ptr |= (bits << 22);
468	}
469	break;
470	default:
471		TCU_FAIL("Invalid channel");
472	}
473}
474
475void TexImageUtils::setRefcolour (glu::CallLogWrapper gl, glw::GLdouble col)
476{
477	switch (m_format)
478	{
479	case GL_RED:
480	case GL_RG:
481	case GL_RGB:
482	case GL_RGBA:
483		gl.glUniform4f(gl.glGetUniformLocation(prog->getProgram(), "refcolour"),
484					   m_num_channels > 0 ? col : 0.0f,
485					   m_num_channels > 1 ? col : 0.0f,
486					   m_num_channels > 2 ? col : 0.0f,
487					   1.0f);
488		break;
489	default:
490		switch (m_type)
491		{
492		case GL_UNSIGNED_BYTE:
493			setUnsignedRefcolour<glw::GLubyte>(gl, col);
494			break;
495		case GL_BYTE:
496			setSignedRefcolour<glw::GLubyte>(gl, col);
497			break;
498		case GL_UNSIGNED_SHORT:
499		case GL_UNSIGNED_SHORT_5_6_5:
500		case GL_UNSIGNED_SHORT_4_4_4_4:
501		case GL_UNSIGNED_SHORT_5_5_5_1:
502			setUnsignedRefcolour<glw::GLushort>(gl, col);
503			break;
504		case GL_SHORT:
505			setSignedRefcolour<glw::GLushort>(gl, col);
506			break;
507		case GL_UNSIGNED_INT:
508			setUnsignedRefcolour<glw::GLuint>(gl, col);
509			break;
510		case GL_UNSIGNED_INT_2_10_10_10_REV:
511			setRGB10A2Refcolour(gl, col);
512			break;
513		case GL_INT:
514			setSignedRefcolour<glw::GLuint>(gl, col);
515			break;
516		default:
517			TCU_FAIL("Invalid type");
518		}
519	}
520}
521
522template <typename T>
523void TexImageUtils::setUnsignedRefcolour (glu::CallLogWrapper gl, glw::GLdouble col)
524{
525	static const T max = -1;
526	const glw::GLdouble d_max   = (glw::GLdouble)max;
527	const glw::GLdouble d_value = d_max * col;
528	const T t_value = (T)d_value;
529
530	unsigned int refcol[4] =
531	{
532		m_num_channels > 0 ? t_value : 0u,
533		m_num_channels > 1 ? t_value : 0u,
534		m_num_channels > 2 ? t_value : 0u,
535		255u,
536	};
537
538	gl.glUniform4uiv(gl.glGetUniformLocation(prog->getProgram(), "refcolour"), 1,
539					 refcol);
540}
541
542template <typename T>
543void TexImageUtils::setSignedRefcolour (glu::CallLogWrapper gl, glw::GLdouble col)
544{
545	static const T umax = -1;
546	static const T max  = umax >> 1;
547
548	const glw::GLdouble d_max   = (glw::GLdouble)max;
549	const glw::GLdouble d_value = d_max * col;
550	const T t_value = (T)d_value;
551
552	int refcol[4] =
553	{
554		(m_num_channels > 0 ? (int)t_value : 0),
555		(m_num_channels > 1 ? (int)t_value : 0),
556		(m_num_channels > 2 ? (int)t_value : 0),
557		255,
558	};
559
560	gl.glUniform4iv(gl.glGetUniformLocation(prog->getProgram(), "refcolour"), 1,
561					refcol);
562}
563
564void TexImageUtils::setRGB10A2Refcolour (glu::CallLogWrapper gl, glw::GLdouble col)
565{
566	unsigned int max_channel_value = 1023u;
567
568	const glw::GLdouble d_max_channel_value = (glw::GLdouble)max_channel_value;
569	const glw::GLdouble d_value = (glw::GLdouble)d_max_channel_value * col;
570	unsigned int t_value = (unsigned int)d_value;
571
572	unsigned int refcol[4] =
573	{
574		(m_num_channels > 0 ? t_value : 0u),
575		(m_num_channels > 1 ? t_value : 0u),
576		(m_num_channels > 2 ? t_value : 0u),
577		255u,
578	};
579
580	gl.glUniform4uiv(gl.glGetUniformLocation(prog->getProgram(), "refcolour"), 1,
581					 refcol);
582}
583
584bool TexImageUtils::verify(tcu::Surface dst, tcu::Surface *errMask)
585{
586	*errMask = tcu::Surface (dst.getWidth(), dst.getHeight());
587	tcu::clear(errMask->getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
588	bool pass = true;
589
590	for (int y = 0; y < dst.getHeight(); y++)
591	{
592		for (int x = 0; x < dst.getWidth(); x++)
593		{
594			if (dst.getPixel(x, y) != tcu::RGBA::green())
595			{
596				pass = false;
597				errMask->setPixel(x, y, tcu::RGBA::red());
598			}
599		}
600	}
601
602	return pass;
603}
604
605class TexImage2DCase : public deqp::TestCase
606					 , public sglr::ContextWrapper
607					 , public TexImageUtils
608{
609public:
610	TexImage2DCase (deqp::Context& context, const char* name, const char* desc,
611					deUint32 internalFormat,
612					int rect_w, int rect_h,
613					int subrect_x0, int subrect_y0,
614					int subrect_w, int subrect_h,
615					glu::GLSLVersion glsl_version);
616	~TexImage2DCase (void);
617	IterateResult iterate (void);
618protected:
619	void generateSrcData();
620	void createTexture (void);
621	void createShader (void);
622	tcu::Surface renderToSurf (void);
623	void cleanup (void);
624};
625
626TexImage2DCase::TexImage2DCase (deqp::Context& context,
627								const char* name,
628								const char* desc,
629								deUint32 internalFormat,
630								int rect_w,
631								int rect_h,
632								int subrect_x0,
633								int subrect_y0,
634								int subrect_w,
635								int subrect_h,
636								glu::GLSLVersion glsl_version)
637	: TestCase(context, name, desc)
638	, TexImageUtils(internalFormat,
639					rect_w, rect_h, 1,
640					subrect_x0, subrect_y0, 0,
641					subrect_w, subrect_h, 1,
642					glsl_version)
643{
644}
645
646TexImage2DCase::~TexImage2DCase(void)
647{
648}
649
650TexImage2DCase::IterateResult TexImage2DCase::iterate(void)
651{
652	glu::RenderContext& renderCtx = TestCase::m_context.getRenderContext();
653	tcu::TestLog& log = m_testCtx.getLog();
654	tcu::Surface dst, errMask;
655
656	bool pass = true;
657
658	sglr::GLContext gl_ctx (renderCtx,
659							log,
660							sglr::GLCONTEXT_LOG_CALLS,
661							tcu::IVec4(0, 0, m_subcuboid_w, m_subcuboid_h));
662
663	setContext((sglr::Context*)&gl_ctx);
664
665	generateSrcData();
666	createTexture();
667	createShader();
668	dst = renderToSurf();
669
670	pass = verify(dst, &errMask);
671
672	cleanup();
673
674	if (pass)
675	{
676		m_testCtx.getLog()
677		<< tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage
678		<< tcu::TestLog::ImageSet("ImageVerification", "Image verification")
679		<< tcu::TestLog::Image("Result", "Rendered result", dst.getAccess())
680		<< tcu::TestLog::EndImageSet;
681	}
682	else
683	{
684		m_testCtx.getLog()
685		<< tcu::TestLog::Message << "Image is invalid" << tcu::TestLog::EndMessage
686		<< tcu::TestLog::ImageSet("ErrorVerification", "Image verification")
687		<< tcu::TestLog::Image("Result", "Rendered result", dst.getAccess())
688		<< tcu::TestLog::Image("ErrorMask", "Error mask", errMask.getAccess())
689		<< tcu::TestLog::EndImageSet;
690	}
691
692	m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
693							pass ? "Pass" : "Fail");
694
695	return STOP;
696}
697
698void TexImage2DCase::generateSrcData()
699{
700	m_src_data = new glw::GLubyte[m_cuboid_w * m_cuboid_h * m_pixelsize]();
701
702	glw::GLdouble col = 0.0;
703
704	for (int y = 0; y < m_cuboid_h; y++)
705	{
706		for (int x = 0; x < m_cuboid_w; x++)
707		{
708			if (inrange(y, m_subcuboid_y0, m_subcuboid_y0 + m_subcuboid_h) &&
709				inrange(x, m_subcuboid_x0, m_subcuboid_x0 + m_subcuboid_w))
710				col = 1.0;
711			else
712				col = 0.0;
713			int offset = y * m_cuboid_w * m_pixelsize +
714						 x * m_pixelsize;
715			writePixel(m_src_data + offset, col);
716		}
717	}
718}
719
720void TexImage2DCase::createTexture (void)
721{
722	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
723							m_testCtx.getLog());
724
725	gl.glGenTextures(1, &tex);
726	gl.glBindTexture(GL_TEXTURE_2D, tex);
727	gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
728	gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
729
730	gl.glPixelStorei(GL_UNPACK_ROW_LENGTH,	m_cuboid_w);
731	gl.glPixelStorei(GL_UNPACK_SKIP_ROWS,   m_subcuboid_y0);
732	gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_subcuboid_x0);
733
734	gl.glTexImage2D(GL_TEXTURE_2D,
735					0,
736					m_internalFormat,
737					m_subcuboid_w,
738					m_subcuboid_h,
739					0,
740					m_format,
741					m_type,
742					m_src_data);
743
744	gl.glPixelStorei(GL_UNPACK_ROW_LENGTH,	 0);
745	gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
746	gl.glPixelStorei(GL_UNPACK_SKIP_ROWS,	 0);
747}
748
749void TexImage2DCase::createShader (void)
750{
751	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
752							m_testCtx.getLog());
753
754	const tcu::StringTemplate vs_src (vs_template_src);
755	const tcu::StringTemplate fs_src (fs_template_src);
756
757	std::map<std::string,std::string> params;
758	params["GLSL_VERSION"]	 = getGLSLVersionDeclaration(m_glsl_version);
759	params["TEXCOORDS_TYPE"] = "vec2";
760	params["LAYER"]			 = "";
761	params["TEXCOORDS"]		 = "pos.xy";
762	params["CONDITION"]		 = "colour.rgb == refcolour.rgb";
763
764	switch (m_format)
765	{
766	case GL_RED_INTEGER:
767	case GL_RG_INTEGER:
768	case GL_RGB_INTEGER:
769	case GL_RGBA_INTEGER:
770		switch (m_type)
771		{
772		case GL_BYTE:
773		case GL_SHORT:
774		case GL_INT:
775			params["SAMPLER_TYPE"] = "isampler2D";
776			params["COL_TYPE"]	 = "ivec4";
777			break;
778		default:
779			params["SAMPLER_TYPE"] = "usampler2D";
780			params["COL_TYPE"]	   = "uvec4";
781			break;
782		}
783		break;
784	default:
785		params["SAMPLER_TYPE"] = "sampler2D";
786		params["COL_TYPE"]	   = "vec4";
787		break;
788	}
789
790	prog = new glu::ShaderProgram(m_context.getRenderContext(),
791								  glu::ProgramSources() <<
792								  glu::VertexSource(vs_src.specialize(params)) <<
793								  glu::FragmentSource(fs_src.specialize(params)));
794
795	if (!prog->isOk())
796	{
797		m_testCtx.getLog()
798			<< tcu::TestLog::Message << ""
799			<< tcu::TestLog::EndMessage
800			<< tcu::TestLog::ShaderProgram(false, "")
801			<< tcu::TestLog::Shader(QP_SHADER_TYPE_VERTEX,
802									prog->getShaderInfo(glu::SHADERTYPE_VERTEX,
803														0).source,
804									false,
805									prog->getShaderInfo(glu::SHADERTYPE_VERTEX,
806														0).infoLog)
807
808			<< tcu::TestLog::Shader(QP_SHADER_TYPE_FRAGMENT,
809									prog->getShaderInfo(glu::SHADERTYPE_FRAGMENT,
810														0).source,
811									false,
812									prog->getShaderInfo(glu::SHADERTYPE_FRAGMENT,
813														0).infoLog)
814			<< tcu::TestLog::EndShaderProgram;
815		TCU_FAIL("Shader creation failed");
816	}
817
818	gl.glUseProgram(prog->getProgram());
819	gl.glUniform1i(gl.glGetUniformLocation(prog->getProgram(), "sampler"), 0);
820}
821
822tcu::Surface TexImage2DCase::renderToSurf (void)
823{
824	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
825							m_testCtx.getLog());
826	gl.glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
827	gl.glClear(GL_COLOR_BUFFER_BIT);
828
829	static const float vertexPositions[4*3] =
830	{
831		-1.0, -1.0, -1.0f,
832		 1.0, -1.0,  0.0f,
833		-1.0,  1.0,  0.0f,
834		 1.0,  1.0,  1.0f,
835	};
836
837	static const deUint16 indices[6] = { 0, 1, 2, 2, 1, 3 };
838
839	const glu::VertexArrayBinding attrBindings[] =
840	{
841		glu::va::Float("pos", 3, 4, 0, &vertexPositions[0])
842	};
843
844	gl.glViewport(0, 0, m_subcuboid_w, m_subcuboid_h);
845	setRefcolour(gl, 1.0);
846	glu::draw(m_context.getRenderContext(),
847			  prog->getProgram(),
848			  DE_LENGTH_OF_ARRAY(attrBindings),
849			  &attrBindings[0],
850			  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
851
852	tcu::Surface dst;
853	dst.setSize(m_subcuboid_w, m_subcuboid_h);
854
855	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
856
857	return dst;
858}
859
860void TexImage2DCase::cleanup (void)
861{
862	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
863							m_testCtx.getLog());
864
865	gl.glDeleteTextures(1, &tex);
866	delete[] m_src_data;
867	delete prog;
868}
869
870class TexImage3DCase : public deqp::TestCase
871					 , public sglr::ContextWrapper
872					 , public TexImageUtils
873{
874public:
875	TexImage3DCase (deqp::Context& context, const char* name, const char* desc,
876					deUint32 internalFormat,
877					int cuboid_w, int cuboid_h, int cuboid_d,
878					int subcuboid_x0, int subrect_y0, int subcuboid_z0,
879					int subcuboid_w, int subcuboid_h, int subcuboid_d,
880					glu::GLSLVersion glsl_version);
881	~TexImage3DCase (void);
882	IterateResult iterate (void);
883protected:
884	void generateSrcData();
885	void createTexture (void);
886	void createShader (void);
887	tcu::Surface renderToSurf (int layer);
888	void cleanup (void);
889};
890
891TexImage3DCase::TexImage3DCase (deqp::Context& context,
892								const char* name,
893								const char* desc,
894								deUint32 internalFormat,
895								int cuboid_w,
896								int cuboid_h,
897								int cuboid_d,
898								int subcuboid_x0,
899								int subcuboid_y0,
900								int subcuboid_z0,
901								int subcuboid_w,
902								int subcuboid_h,
903								int subcuboid_d,
904								glu::GLSLVersion glsl_version)
905	: TestCase(context, name, desc)
906	, TexImageUtils(internalFormat,
907					cuboid_w, cuboid_h, cuboid_d,
908					subcuboid_x0, subcuboid_y0, subcuboid_z0,
909					subcuboid_w, subcuboid_h, subcuboid_d,
910					glsl_version)
911{
912}
913
914TexImage3DCase::~TexImage3DCase(void)
915{
916}
917
918TexImage3DCase::IterateResult TexImage3DCase::iterate(void)
919{
920	glu::RenderContext& renderCtx = TestCase::m_context.getRenderContext();
921	tcu::TestLog& log = m_testCtx.getLog();
922	tcu::Surface dst, errMask;
923
924	bool pass = true;
925
926	sglr::GLContext gl_ctx (renderCtx,
927							log,
928							sglr::GLCONTEXT_LOG_CALLS,
929							tcu::IVec4(0, 0, m_subcuboid_w, m_subcuboid_h));
930
931	setContext((sglr::Context*)&gl_ctx);
932
933	generateSrcData();
934	createTexture();
935	createShader();
936
937	for (int z = 0; z < m_subcuboid_d; z++)
938	{
939		dst = renderToSurf(z);
940
941		bool layer_pass = verify(dst, &errMask);
942
943		if (layer_pass)
944		{
945			m_testCtx.getLog()
946				<< tcu::TestLog::Message << "Layer " << z	 << " is valid"
947				<< tcu::TestLog::EndMessage
948				<< tcu::TestLog::ImageSet("LayerVerification", "Layer verification")
949				<< tcu::TestLog::Image("Result", "Rendered result", dst.getAccess())
950				<< tcu::TestLog::EndImageSet;
951		}
952		else
953		{
954			m_testCtx.getLog()
955				<< tcu::TestLog::Message << "Layer " << z << " is invalid"
956				<< tcu::TestLog::EndMessage
957				<< tcu::TestLog::ImageSet("ErrorVerification", "Layer verification")
958				<< tcu::TestLog::Image("Result", "Rendered result", dst.getAccess())
959				<< tcu::TestLog::Image("ErrorMask", "Error mask", errMask.getAccess())
960				<< tcu::TestLog::EndImageSet;
961		}
962
963		pass &= layer_pass;
964	}
965
966	cleanup();
967
968	if (pass)
969	{
970		m_testCtx.getLog()
971			<< tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
972	}
973	else
974	{
975		m_testCtx.getLog()
976			<< tcu::TestLog::Message << "Image is invalid" << tcu::TestLog::EndMessage;
977	}
978
979	m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
980									pass ? "Pass" : "Fail");
981
982	return STOP;
983}
984
985void TexImage3DCase::generateSrcData()
986{
987	m_src_data = new glw::GLubyte[m_cuboid_w *
988								  m_cuboid_h *
989								  m_cuboid_d *
990								  m_pixelsize]();
991
992	glw::GLdouble col = 0.0;
993
994	for (int z = 0; z < m_cuboid_d; z++)
995	{
996		for (int y = 0; y < m_cuboid_h; y++)
997		{
998			for (int x = 0; x < m_cuboid_w; x++)
999			{
1000				if (inrange(z, m_subcuboid_z0, m_subcuboid_z0 + m_subcuboid_d) &&
1001					inrange(y, m_subcuboid_y0, m_subcuboid_y0 + m_subcuboid_h) &&
1002					inrange(x, m_subcuboid_x0, m_subcuboid_x0 + m_subcuboid_w))
1003					col = 0.125 + (z - m_subcuboid_z0) * 0.125; /* [0.125, 0.250..1.0] */
1004				else
1005					col = 0.0;
1006				int offset = z * m_cuboid_h * m_cuboid_w * m_pixelsize +
1007							 y * m_cuboid_w * m_pixelsize +
1008							 x * m_pixelsize;
1009				writePixel(m_src_data + offset, col);
1010			}
1011		}
1012	}
1013}
1014
1015void TexImage3DCase::createTexture (void)
1016{
1017	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1018							m_testCtx.getLog());
1019
1020	gl.glGenTextures(1, &tex);
1021	gl.glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
1022	gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1023	gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1024
1025	gl.glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_cuboid_h);
1026	gl.glPixelStorei(GL_UNPACK_ROW_LENGTH,	 m_cuboid_w);
1027	gl.glPixelStorei(GL_UNPACK_SKIP_IMAGES,	 m_subcuboid_z0);
1028	gl.glPixelStorei(GL_UNPACK_SKIP_ROWS,	 m_subcuboid_y0);
1029	gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS,	 m_subcuboid_x0);
1030
1031	gl.glTexImage3D(GL_TEXTURE_2D_ARRAY,
1032					0,
1033					m_internalFormat,
1034					m_subcuboid_w,
1035					m_subcuboid_h,
1036					m_subcuboid_d,
1037					0,
1038					m_format,
1039					m_type,
1040					m_src_data);
1041
1042	gl.glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1043	gl.glPixelStorei(GL_UNPACK_ROW_LENGTH,	 0);
1044	gl.glPixelStorei(GL_UNPACK_SKIP_IMAGES,  0);
1045	gl.glPixelStorei(GL_UNPACK_SKIP_ROWS,	 0);
1046	gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS,  0);
1047}
1048
1049void TexImage3DCase::createShader (void)
1050{
1051	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1052							m_testCtx.getLog());
1053
1054	const tcu::StringTemplate vs_src (vs_template_src);
1055	const tcu::StringTemplate fs_src (fs_template_src);
1056
1057	std::map<std::string,std::string> params;
1058	params["GLSL_VERSION"]	 = getGLSLVersionDeclaration(m_glsl_version);
1059	params["TEXCOORDS_TYPE"] = "vec3";
1060	params["LAYER"]			 = "uniform int layer;";
1061	params["TEXCOORDS"]		 = "vec3(pos.xy, layer)";
1062
1063	switch (m_format)
1064	{
1065	case GL_RED_INTEGER:
1066	case GL_RG_INTEGER:
1067	case GL_RGB_INTEGER:
1068	case GL_RGBA_INTEGER:
1069		switch (m_type)
1070		{
1071		case GL_BYTE:
1072		case GL_SHORT:
1073		case GL_INT:
1074			params["SAMPLER_TYPE"] = "isampler2DArray";
1075			params["COL_TYPE"]	 = "ivec4";
1076			params["CONDITION"]	 = "all(lessThan(uvec4(abs(colour - refcolour)).rgb, uvec3(2u)))";
1077			break;
1078		default:
1079			params["SAMPLER_TYPE"] = "usampler2DArray";
1080			params["COL_TYPE"]	   = "uvec4";
1081			params["CONDITION"]	   = "all(lessThan(uvec4(abs(ivec4(colour) - ivec4(refcolour))).rgb, uvec3(2u)))";
1082			break;
1083		}
1084		break;
1085	default:
1086		const tcu::StringTemplate fs_condition ("all(lessThan((abs(colour - refcolour)).rgb, vec3(${EPS})))");
1087		std::map<std::string, std::string> fs_condition_params;
1088		fs_condition_params["EPS"] = std::to_string(getEps(m_internalFormat));
1089		params["SAMPLER_TYPE"] = "sampler2DArray";
1090		params["COL_TYPE"]	  = "vec4";
1091		params["CONDITION"]	  = fs_condition.specialize(fs_condition_params);
1092		break;
1093	}
1094
1095	prog = new glu::ShaderProgram(m_context.getRenderContext(),
1096								  glu::ProgramSources() <<
1097								  glu::VertexSource(vs_src.specialize(params)) <<
1098								  glu::FragmentSource(fs_src.specialize(params)));
1099
1100	if (!prog->isOk())
1101	{
1102		m_testCtx.getLog()
1103			<< tcu::TestLog::Message << ""
1104			<< tcu::TestLog::EndMessage
1105			<< tcu::TestLog::ShaderProgram(false, "")
1106			<< tcu::TestLog::Shader(QP_SHADER_TYPE_VERTEX,
1107									prog->getShaderInfo(glu::SHADERTYPE_VERTEX,
1108														0).source,
1109									false,
1110									prog->getShaderInfo(glu::SHADERTYPE_VERTEX,
1111														0).infoLog)
1112
1113			<< tcu::TestLog::Shader(QP_SHADER_TYPE_FRAGMENT,
1114									prog->getShaderInfo(glu::SHADERTYPE_FRAGMENT,
1115														0).source,
1116									false,
1117									prog->getShaderInfo(glu::SHADERTYPE_FRAGMENT,
1118														0).infoLog)
1119			<< tcu::TestLog::EndShaderProgram;
1120		TCU_FAIL("Shader creation failed");
1121	}
1122
1123	gl.glUseProgram(prog->getProgram());
1124	gl.glUniform1i(gl.glGetUniformLocation(prog->getProgram(), "sampler"), 0);
1125}
1126
1127tcu::Surface TexImage3DCase::renderToSurf (int layer)
1128{
1129	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1130							m_testCtx.getLog());
1131	gl.glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
1132	gl.glClear(GL_COLOR_BUFFER_BIT);
1133
1134	static const float vertexPositions[4*3] =
1135	{
1136		-1.0, -1.0, -1.0f,
1137		 1.0, -1.0,	 0.0f,
1138		-1.0,  1.0,	 0.0f,
1139		1.0,   1.0,	 1.0f,
1140	};
1141
1142	static const deUint16 indices[6] = { 0, 1, 2, 2, 1, 3 };
1143
1144	const glu::VertexArrayBinding attrBindings[] =
1145	{
1146		glu::va::Float("pos", 3, 4, 0, &vertexPositions[0])
1147	};
1148
1149	gl.glViewport(0, 0, m_subcuboid_w, m_subcuboid_h);
1150
1151	gl.glUniform1i(gl.glGetUniformLocation(prog->getProgram(), "layer"), layer);
1152	glw::GLfloat refcol = 0.125 + layer * 0.125;
1153	setRefcolour(gl, refcol);
1154	glu::draw(m_context.getRenderContext(),
1155			  prog->getProgram(),
1156			  DE_LENGTH_OF_ARRAY(attrBindings),
1157			  &attrBindings[0],
1158			  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
1159
1160	tcu::Surface dst;
1161	dst.setSize(m_subcuboid_w, m_subcuboid_h);
1162
1163	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
1164
1165	return dst;
1166}
1167
1168void TexImage3DCase::cleanup (void)
1169{
1170	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1171							m_testCtx.getLog());
1172
1173	gl.glDeleteTextures(1, &tex);
1174	delete[] m_src_data;
1175	delete prog;
1176}
1177
1178class CompressedTexImageUtils
1179{
1180public:
1181	CompressedTexImageUtils (deUint32 internalFormat,
1182							 int cuboid_w, int cuboid_h, int cuboid_d,
1183							 int subcuboid_x0, int subcuboid_y0, int subcuboid_z0,
1184							 int subcuboid_w, int subcuboid_h, int subcuboid_d,
1185							 glu::GLSLVersion glsl_version);
1186	~CompressedTexImageUtils (void);
1187protected:
1188	int getImageSize (int width, int height, int depth);
1189	bool verify(tcu::Surface dst, tcu::Surface *errMask);
1190
1191	glw::GLubyte *m_src_data;
1192	deUint32 tex;
1193	glu::ShaderProgram *prog;
1194
1195	int m_bw;					/* block width */
1196	int m_bh;					/* block height */
1197	int m_bd;					/* block depth */
1198	int m_bs;					/* block size */
1199
1200	deUint32 m_internalFormat;
1201	int m_cuboid_w;
1202	int m_cuboid_h;
1203	int m_cuboid_d;
1204	int m_subcuboid_x0;
1205	int m_subcuboid_y0;
1206	int m_subcuboid_z0;
1207	int m_subcuboid_w;
1208	int m_subcuboid_h;
1209	int m_subcuboid_d;
1210
1211	glu::GLSLVersion m_glsl_version;
1212};
1213
1214CompressedTexImageUtils::CompressedTexImageUtils (deUint32 internalFormat,
1215												  int cuboid_w,
1216												  int cuboid_h,
1217												  int cuboid_d,
1218												  int subcuboid_x0,
1219												  int subcuboid_y0,
1220												  int subcuboid_z0,
1221												  int subcuboid_w,
1222												  int subcuboid_h,
1223												  int subcuboid_d,
1224												  glu::GLSLVersion glsl_version)
1225	: m_internalFormat(internalFormat)
1226	, m_cuboid_w(cuboid_w)
1227	, m_cuboid_h(cuboid_h)
1228	, m_cuboid_d(cuboid_d)
1229	, m_subcuboid_x0(subcuboid_x0)
1230	, m_subcuboid_y0(subcuboid_y0)
1231	, m_subcuboid_z0(subcuboid_z0)
1232	, m_subcuboid_w(subcuboid_w)
1233	, m_subcuboid_h(subcuboid_h)
1234	, m_subcuboid_d(subcuboid_d)
1235	, m_glsl_version(glsl_version)
1236{
1237}
1238
1239CompressedTexImageUtils::~CompressedTexImageUtils(void)
1240{
1241}
1242
1243int CompressedTexImageUtils::getImageSize (int width, int height, int depth)
1244{
1245	return (width / m_bw + (width % m_bw > 0)) *
1246		   (height / m_bh + (height % m_bh > 0)) *
1247		   (depth / m_bd + (depth % m_bd > 0)) *
1248		   m_bs;
1249}
1250
1251bool CompressedTexImageUtils::verify(tcu::Surface dst, tcu::Surface *errMask)
1252{
1253	*errMask = tcu::Surface (dst.getWidth(), dst.getHeight());
1254	tcu::clear(errMask->getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1255	bool pass = true;
1256
1257	for (int y = 0; y < dst.getHeight(); y++)
1258	{
1259		for (int x = 0; x < dst.getWidth(); x++)
1260		{
1261			if (dst.getPixel(x, y) != tcu::RGBA::green())
1262			{
1263				pass = false;
1264				errMask->setPixel(x, y, tcu::RGBA::red());
1265			}
1266		}
1267	}
1268
1269	return pass;
1270}
1271
1272class CompressedTexImage2DCase : public deqp::TestCase
1273							   , public sglr::ContextWrapper
1274							   , public CompressedTexImageUtils
1275{
1276public:
1277	CompressedTexImage2DCase (deqp::Context& context, const char *name, const char *desc,
1278							  deUint32 internalFormat,
1279							  int cuboid_w, int cuboid_h,
1280							  int subcuboid_x0, int subcuboid_y0,
1281							  int subcuboid_w, int subcuboid_h,
1282							  glu::GLSLVersion glsl_version);
1283	~CompressedTexImage2DCase (void);
1284	IterateResult iterate (void);
1285protected:
1286	void generateSrcData_s3tc (void);
1287	void generateSrcData_astc (void);
1288	void createTexture (void);
1289	void createShader (void);
1290	tcu::Surface renderToSurf (void);
1291	void cleanup (void);
1292};
1293
1294CompressedTexImage2DCase::CompressedTexImage2DCase (deqp::Context& context,
1295													const char *name,
1296													const char *desc,
1297													deUint32 internalFormat,
1298													int cuboid_w,
1299													int cuboid_h,
1300													int subcuboid_x0,
1301													int subcuboid_y0,
1302													int subcuboid_w,
1303													int subcuboid_h,
1304													glu::GLSLVersion glsl_version)
1305	: TestCase(context, name, desc)
1306	, CompressedTexImageUtils(internalFormat,
1307							  cuboid_w,
1308							  cuboid_h,
1309							  1,
1310							  subcuboid_x0,
1311							  subcuboid_y0,
1312							  0,
1313							  subcuboid_w,
1314							  subcuboid_h,
1315							  1,
1316							  glsl_version)
1317{
1318}
1319
1320CompressedTexImage2DCase::~CompressedTexImage2DCase (void)
1321{
1322}
1323
1324CompressedTexImage2DCase::IterateResult CompressedTexImage2DCase::iterate (void)
1325{
1326	glu::RenderContext& renderCtx = TestCase::m_context.getRenderContext();
1327	const glu::ContextInfo& ctxInfo = m_context.getContextInfo();
1328	tcu::TestLog& log = m_testCtx.getLog();
1329	tcu::Surface dst, errMask;
1330
1331	bool pass = true;
1332
1333	sglr::GLContext gl_ctx (renderCtx,
1334							log,
1335							sglr::GLCONTEXT_LOG_CALLS,
1336							tcu::IVec4(0, 0, m_subcuboid_w, m_subcuboid_h));
1337
1338	setContext((sglr::Context*)&gl_ctx);
1339
1340	if (!glu::contextSupports(renderCtx.getType(), glu::ApiType::core(4, 2)) &&
1341		!ctxInfo.isExtensionSupported("GL_ARB_compressed_texture_pixel_storage"))
1342	{
1343		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
1344								"GL_ARB_compressed_texture_pixel_storage extension is not supported");
1345		return STOP;
1346	}
1347
1348	switch (m_internalFormat)
1349	{
1350	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1351		if (!ctxInfo.isExtensionSupported("GL_EXT_texture_compression_s3tc"))
1352		{
1353			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
1354									"GL_EXT_texture_compression_s3tc extension is not supported");
1355			return STOP;
1356		}
1357
1358		m_bw = 4;
1359		m_bh = 4;
1360		m_bd = 1;
1361		m_bs = 8;
1362
1363		generateSrcData_s3tc();
1364		break;
1365	case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
1366		if (!ctxInfo.isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
1367		{
1368			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
1369									"GL_KHR_texture_compression_astc_ldr extension is not supported");
1370			return STOP;
1371		}
1372		m_bw = 8;
1373		m_bh = 5;
1374		m_bd = 1;
1375		m_bs = 16;
1376
1377		generateSrcData_astc();
1378		break;
1379	default:
1380		TCU_FAIL("Invalid internal format");
1381	}
1382
1383	createTexture();
1384	createShader();
1385
1386	dst = renderToSurf();
1387	pass = verify(dst, &errMask);
1388
1389	cleanup();
1390
1391	if (pass)
1392	{
1393		m_testCtx.getLog()
1394		<< tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage
1395		<< tcu::TestLog::ImageSet("ImageVerification", "Image verification")
1396		<< tcu::TestLog::Image("Result", "Rendered result", dst.getAccess())
1397		<< tcu::TestLog::EndImageSet;
1398	}
1399	else
1400	{
1401		m_testCtx.getLog()
1402		<< tcu::TestLog::Message << "Image is invalid" << tcu::TestLog::EndMessage
1403		<< tcu::TestLog::ImageSet("ErrorVerification", "Image verification")
1404		<< tcu::TestLog::Image("Result", "Rendered result", dst.getAccess())
1405		<< tcu::TestLog::Image("ErrorMask", "Error mask", errMask.getAccess())
1406		<< tcu::TestLog::EndImageSet;
1407	}
1408
1409	m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1410							pass ? "Pass" : "Fail");
1411
1412	return STOP;
1413}
1414
1415void CompressedTexImage2DCase::generateSrcData_s3tc (void)
1416{
1417	deUint64 *src = new deUint64[m_cuboid_w / m_bw * m_cuboid_h / m_bh];
1418
1419	deUint64 col = 0x0;
1420
1421	for (int y = 0; y < m_cuboid_h; y += m_bh)
1422	{
1423		for (int x = 0; x < m_cuboid_w; x += m_bw)
1424		{
1425			if (inrange(x, m_subcuboid_x0, m_subcuboid_x0 + m_subcuboid_w) &&
1426				inrange(y, m_subcuboid_y0, m_subcuboid_y0 + m_subcuboid_h))
1427			{
1428				col = 0xffff;
1429			}
1430			else
1431			{
1432				col = 0x0;
1433			}
1434			int index = (y / m_bh) * (m_cuboid_w / m_bw) +
1435							(x / m_bw);
1436			src[index] = col;
1437		}
1438	}
1439
1440	m_src_data = (glw::GLubyte*)src;
1441}
1442
1443void CompressedTexImage2DCase::generateSrcData_astc (void)
1444{
1445	deUint64 col = 0x0;
1446	deUint64 mask = 0xfffffffffffffdfc;
1447
1448	int img_size = 2 * (m_cuboid_w / m_bw + (m_cuboid_w % m_bw > 0)) *
1449				   (m_cuboid_h / m_bh + (m_cuboid_h % m_bh > 0));
1450
1451	deUint64 *src = new deUint64[img_size];
1452
1453	for (int y = 0; y < m_cuboid_h; y += m_bh)
1454	{
1455		for (int x = 0; x < m_cuboid_w; x += m_bw)
1456		{
1457			if (inrange(x, m_subcuboid_x0, m_subcuboid_x0 + m_subcuboid_w) &&
1458				inrange(y, m_subcuboid_y0, m_subcuboid_y0 + m_subcuboid_h))
1459			{
1460				col = 0xffffffffffffffff; /* (1.0, 1.0, 1.0) */
1461			}
1462			else
1463			{
1464				col = 0x0; /* (0.0, 0.0, 0.0) */
1465			}
1466			int index = (y / m_bh) * (m_cuboid_w / m_bw + (m_cuboid_w % m_bw > 0)) +
1467						(x / m_bw);
1468			src[2 * index] = mask;
1469			src[2 * index + 1] = col;
1470		}
1471	}
1472
1473	m_src_data = (glw::GLubyte*)src;
1474}
1475
1476void CompressedTexImage2DCase::createTexture (void)
1477{
1478	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1479							m_testCtx.getLog());
1480
1481	gl.glGenTextures(1, &tex);
1482	gl.glBindTexture(GL_TEXTURE_2D, tex);
1483	gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1484	gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1485
1486	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE,	 m_bs);
1487	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH,	 m_bw);
1488	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, m_bh);
1489
1490	gl.glPixelStorei(GL_UNPACK_ROW_LENGTH,	 m_cuboid_w);
1491	gl.glPixelStorei(GL_UNPACK_SKIP_ROWS,	 m_subcuboid_y0);
1492	gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS, m_subcuboid_x0);
1493
1494	gl.glCompressedTexImage2D(GL_TEXTURE_2D,
1495							  0,
1496							  m_internalFormat,
1497							  m_subcuboid_w,
1498							  m_subcuboid_h,
1499							  0,
1500							  getImageSize(m_subcuboid_w,
1501										   m_subcuboid_h,
1502										   m_subcuboid_d),
1503							  m_src_data);
1504
1505	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE,	 0);
1506	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH,	 0);
1507	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT,  0);
1508
1509	gl.glPixelStorei(GL_UNPACK_ROW_LENGTH,	 0);
1510	gl.glPixelStorei(GL_UNPACK_SKIP_ROWS,	 0);
1511	gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS,  0);
1512}
1513
1514void CompressedTexImage2DCase::createShader (void)
1515{
1516	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1517							m_testCtx.getLog());
1518
1519	const tcu::StringTemplate vs_src (vs_template_src);
1520	const tcu::StringTemplate fs_src (fs_template_src);
1521
1522	std::map<std::string,std::string> params;
1523	params["GLSL_VERSION"]	 = getGLSLVersionDeclaration(m_glsl_version);
1524	params["TEXCOORDS_TYPE"] = "vec2";
1525	params["LAYER"]			 = "";
1526	params["TEXCOORDS"]		 = "pos.xy";
1527	params["SAMPLER_TYPE"]	 = "sampler2D";
1528	params["COL_TYPE"]		 = "vec4";
1529	params["CONDITION"]		 = "colour.rgb == refcolour.rgb";
1530
1531	prog = new glu::ShaderProgram(m_context.getRenderContext(),
1532								  glu::ProgramSources() <<
1533								  glu::VertexSource(vs_src.specialize(params)) <<
1534								  glu::FragmentSource(fs_src.specialize(params)));
1535
1536	if (!prog->isOk())
1537	{
1538		m_testCtx.getLog()
1539			<< tcu::TestLog::Message << ""
1540			<< tcu::TestLog::EndMessage
1541			<< tcu::TestLog::ShaderProgram(false, "")
1542			<< tcu::TestLog::Shader(QP_SHADER_TYPE_VERTEX,
1543									prog->getShaderInfo(glu::SHADERTYPE_VERTEX,
1544														0).source,
1545									false,
1546									prog->getShaderInfo(glu::SHADERTYPE_VERTEX,
1547														0).infoLog)
1548
1549			<< tcu::TestLog::Shader(QP_SHADER_TYPE_FRAGMENT,
1550									prog->getShaderInfo(glu::SHADERTYPE_FRAGMENT,
1551														0).source,
1552									false,
1553									prog->getShaderInfo(glu::SHADERTYPE_FRAGMENT,
1554														0).infoLog)
1555			<< tcu::TestLog::EndShaderProgram;
1556		TCU_FAIL("Shader creation failed");
1557	}
1558
1559	gl.glUseProgram(prog->getProgram());
1560	gl.glUniform1i(gl.glGetUniformLocation(prog->getProgram(), "sampler"), 0);
1561}
1562
1563tcu::Surface CompressedTexImage2DCase::renderToSurf (void)
1564{
1565	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1566							m_testCtx.getLog());
1567
1568	gl.glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
1569	gl.glClear(GL_COLOR_BUFFER_BIT);
1570
1571	static const float vertexPositions[4*3] =
1572	{
1573		-1.0, -1.0, -1.0f,
1574		 1.0, -1.0,	 0.0f,
1575		-1.0,  1.0,	 0.0f,
1576		 1.0,  1.0,	 1.0f,
1577	};
1578
1579	static const deUint16 indices[6] = { 0, 1, 2, 2, 1, 3 };
1580
1581	const glu::VertexArrayBinding attrBindings[] =
1582	{
1583		glu::va::Float("pos", 3, 4, 0, &vertexPositions[0])
1584	};
1585
1586	gl.glViewport(0, 0, m_subcuboid_w, m_subcuboid_h);
1587
1588	glw::GLfloat refcol = 1.0f;
1589
1590	gl.glUniform4f(gl.glGetUniformLocation(prog->getProgram(), "refcolour"),
1591				   refcol, refcol, refcol, 1.0f);
1592
1593	glu::draw(m_context.getRenderContext(),
1594			  prog->getProgram(),
1595			  DE_LENGTH_OF_ARRAY(attrBindings),
1596			  &attrBindings[0],
1597			  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
1598
1599	tcu::Surface dst;
1600	dst.setSize(m_subcuboid_w, m_subcuboid_h);
1601
1602	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
1603
1604	return dst;
1605}
1606
1607void CompressedTexImage2DCase::cleanup (void)
1608{
1609	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1610							m_testCtx.getLog());
1611
1612	gl.glDeleteTextures(1, &tex);
1613	delete[] m_src_data;
1614	delete prog;
1615}
1616
1617class CompressedTexImage3DCase : public deqp::TestCase
1618							   , public sglr::ContextWrapper
1619							   , public CompressedTexImageUtils
1620{
1621public:
1622	CompressedTexImage3DCase (deqp::Context& context, const char *name, const char *desc,
1623							  deUint32 internalFormat,
1624							  int cuboid_w, int cuboid_h, int cuboid_d,
1625							  int subcuboid_x0, int subcuboid_y0, int subcuboid_z0,
1626							  int subcuboid_w, int subcuboid_h, int subcuboid_d,
1627							  glu::GLSLVersion glsl_version);
1628	~CompressedTexImage3DCase (void);
1629	IterateResult iterate (void);
1630protected:
1631	void generateSrcData_s3tc (void);
1632	void generateSrcData_astc (void);
1633	void createTexture (void);
1634	void createShader (void);
1635	tcu::Surface renderToSurf (int layer);
1636	void cleanup (void);
1637};
1638
1639CompressedTexImage3DCase::CompressedTexImage3DCase (deqp::Context& context,
1640													const char *name,
1641													const char *desc,
1642													deUint32 internalFormat,
1643													int cuboid_w,
1644													int cuboid_h,
1645													int cuboid_d,
1646													int subcuboid_x0,
1647													int subcuboid_y0,
1648													int subcuboid_z0,
1649													int subcuboid_w,
1650													int subcuboid_h,
1651													int subcuboid_d,
1652													glu::GLSLVersion glsl_version)
1653	: TestCase(context, name, desc)
1654	, CompressedTexImageUtils(internalFormat,
1655							  cuboid_w,
1656							  cuboid_h,
1657							  cuboid_d,
1658							  subcuboid_x0,
1659							  subcuboid_y0,
1660							  subcuboid_z0,
1661							  subcuboid_w,
1662							  subcuboid_h,
1663							  subcuboid_d,
1664							  glsl_version)
1665{
1666}
1667
1668CompressedTexImage3DCase::~CompressedTexImage3DCase (void)
1669{
1670}
1671
1672CompressedTexImage3DCase::IterateResult CompressedTexImage3DCase::iterate (void)
1673{
1674	glu::RenderContext& renderCtx = TestCase::m_context.getRenderContext();
1675	const glu::ContextInfo& ctxInfo = m_context.getContextInfo();
1676	tcu::TestLog& log = m_testCtx.getLog();
1677	tcu::Surface dst, errMask;
1678
1679	bool pass = true;
1680
1681	sglr::GLContext gl_ctx (renderCtx,
1682							log,
1683							sglr::GLCONTEXT_LOG_CALLS,
1684							tcu::IVec4(0, 0, m_subcuboid_w, m_subcuboid_h));
1685
1686	setContext((sglr::Context*)&gl_ctx);
1687
1688	if (!glu::contextSupports(renderCtx.getType(), glu::ApiType::core(4, 2)) &&
1689		!ctxInfo.isExtensionSupported("GL_ARB_compressed_texture_pixel_storage"))
1690	{
1691		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
1692								"GL_ARB_compressed_texture_pixel_storage extension is not supported");
1693		return STOP;
1694	}
1695
1696	switch (m_internalFormat)
1697	{
1698	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1699		if (!ctxInfo.isExtensionSupported("GL_EXT_texture_compression_s3tc"))
1700		{
1701			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
1702									"GL_EXT_texture_compression_s3tc extension is not supported");
1703			return STOP;
1704		}
1705
1706		m_bw = 4;
1707		m_bh = 4;
1708		m_bd = 1;
1709		m_bs = 8;
1710
1711		generateSrcData_s3tc();
1712		break;
1713	case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
1714		if (!ctxInfo.isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
1715		{
1716			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
1717									"GL_KHR_texture_compression_astc_ldr extension is not supported");
1718			return STOP;
1719		}
1720		m_bw = 8;
1721		m_bh = 5;
1722		m_bd = 1;
1723		m_bs = 16;
1724
1725		generateSrcData_astc();
1726		break;
1727	default:
1728		TCU_FAIL("Invalid internal format");
1729	}
1730
1731	createTexture();
1732	createShader();
1733
1734	for (int z = 0; z < m_subcuboid_d; z++)
1735	{
1736		dst = renderToSurf(z);
1737
1738		bool layer_pass = verify(dst, &errMask);
1739
1740		if (layer_pass)
1741		{
1742			m_testCtx.getLog()
1743				<< tcu::TestLog::Message << "Layer " << z	 << " is valid"
1744				<< tcu::TestLog::EndMessage
1745				<< tcu::TestLog::ImageSet("LayerVerification", "Layer verification")
1746				<< tcu::TestLog::Image("Result", "Rendered result", dst.getAccess())
1747				<< tcu::TestLog::EndImageSet;
1748		}
1749		else
1750		{
1751			m_testCtx.getLog()
1752				<< tcu::TestLog::Message << "Layer " << z << " is invalid"
1753				<< tcu::TestLog::EndMessage
1754				<< tcu::TestLog::ImageSet("ErrorVerification", "Layer verification")
1755				<< tcu::TestLog::Image("Result", "Rendered result", dst.getAccess())
1756				<< tcu::TestLog::Image("ErrorMask", "Error mask", errMask.getAccess())
1757				<< tcu::TestLog::EndImageSet;
1758		}
1759
1760		pass &= layer_pass;
1761	}
1762
1763	cleanup();
1764
1765	if (pass)
1766	{
1767		m_testCtx.getLog()
1768			<< tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
1769	}
1770	else
1771	{
1772		m_testCtx.getLog()
1773			<< tcu::TestLog::Message << "Image is invalid" << tcu::TestLog::EndMessage;
1774	}
1775
1776	m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1777							pass ? "Pass" : "Fail");
1778
1779	return STOP;
1780}
1781
1782void CompressedTexImage3DCase::generateSrcData_s3tc()
1783{
1784	deUint64 *src = new deUint64[m_cuboid_w / m_bw *
1785								 m_cuboid_h / m_bh *
1786								 m_cuboid_d / m_bd];
1787
1788	deUint64 col_list[] =
1789	{
1790		0x18E3,					/* (0.125, 0.125, 0.125) */
1791		0x39E7,					/* (0.250, 0.250, 0.250) */
1792		0x5AEB,					/* (0.375, 0.375, 0.375) */
1793		0x7BEF,					/* (0.500, 0.500, 0.500) */
1794		0x9CF3,					/* (0.625, 0.625, 0.625) */
1795		0xBDF7,					/* (0.750, 0.750, 0.750) */
1796		0xDEFB,					/* (0.875, 0.875, 0.875) */
1797		0xffff,					/* (1.000, 1.000, 1.000) */
1798	};
1799
1800	deUint64 col = 0x0;
1801
1802	for (int z = 0; z < m_cuboid_d; z += m_bd)
1803	{
1804		for (int y = 0; y < m_cuboid_h; y += m_bh)
1805		{
1806			for (int x = 0; x < m_cuboid_w; x += m_bw)
1807			{
1808				if (inrange(x, m_subcuboid_x0, m_subcuboid_x0 + m_subcuboid_w) &&
1809					inrange(y, m_subcuboid_y0, m_subcuboid_y0 + m_subcuboid_h) &&
1810					inrange(z, m_subcuboid_z0, m_subcuboid_z0 + m_subcuboid_d))
1811					col = col_list[z % 8];
1812				else
1813					col = 0x0;
1814
1815				int index = (z / m_bd) * (m_cuboid_h / m_bh) * (m_cuboid_w / m_bw) +
1816							(y / m_bh) * (m_cuboid_w / m_bw) +
1817							(x / m_bw);
1818				src[index] = col;
1819			}
1820		}
1821	}
1822
1823	m_src_data = (glw::GLubyte*)src;
1824}
1825
1826void CompressedTexImage3DCase::generateSrcData_astc (void)
1827{
1828	deUint64 col_list[] =
1829	{
1830		0xffff1fff1fff1fff,		/* (0.125, 0.125, 0.125) */
1831		0xffff3fff3fff3fff,		/* (0.250, 0.250, 0.250) */
1832		0xffff5fff5fff5fff,		/* (0.375, 0.375, 0.375) */
1833		0xffff7fff7fff7fff,		/* (0.500, 0.500, 0.500) */
1834		0xffff9fff9fff9fff,		/* (0.625, 0.625, 0.625) */
1835		0xffffbfffbfffbfff,		/* (0.750, 0.750, 0.750) */
1836		0xffffdfffdfffdfff,		/* (0.875, 0.875, 0.875) */
1837		0xffffffffffffffff,		/* (1.000, 1.000, 1.000) */
1838	};
1839	deUint64 col = 0x0;
1840	deUint64 mask = 0xFFFFFFFFFFFFFDFC;
1841
1842	int img_size = 2 * (m_cuboid_w / m_bw + (m_cuboid_w % m_bw > 0)) *
1843					   (m_cuboid_h / m_bh + (m_cuboid_h % m_bh > 0)) *
1844					   (m_cuboid_d / m_bd + (m_cuboid_d % m_bd > 0));
1845
1846	deUint64 *src = new deUint64[img_size];
1847
1848	for (int z = 0; z < m_cuboid_d; z += m_bd)
1849	{
1850		for (int y = 0; y < m_cuboid_h; y += m_bh)
1851		{
1852			for (int x = 0; x < m_cuboid_w; x += m_bw)
1853			{
1854				if (inrange(x, m_subcuboid_x0, m_subcuboid_x0 + m_subcuboid_w) &&
1855					inrange(y, m_subcuboid_y0, m_subcuboid_y0 + m_subcuboid_h) &&
1856					inrange(z, m_subcuboid_z0, m_subcuboid_z0 + m_subcuboid_d))
1857					col = col_list[z % 8];
1858				else
1859					col = 0x0;
1860
1861				int index = (z / m_bd) * (m_cuboid_h / m_bh + (m_cuboid_h % m_bh > 0)) *
1862										 (m_cuboid_w / m_bw + (m_cuboid_w % m_bw > 0)) +
1863							(y / m_bh) * (m_cuboid_w / m_bw + (m_cuboid_w % m_bw > 0)) +
1864							(x / m_bw);
1865				src[2 * index] = mask;
1866				src[2 * index + 1] = col;
1867			}
1868		}
1869	}
1870
1871	m_src_data = (glw::GLubyte*)src;
1872}
1873
1874void CompressedTexImage3DCase::createTexture (void)
1875{
1876	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1877							m_testCtx.getLog());
1878
1879	gl.glGenTextures(1, &tex);
1880	gl.glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
1881	gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1882	gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1883
1884	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE,	 m_bs);
1885	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH,	 m_bw);
1886	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT,  m_bh);
1887	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH,	 m_bd);
1888
1889	gl.glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_cuboid_h);
1890	gl.glPixelStorei(GL_UNPACK_ROW_LENGTH,	 m_cuboid_w);
1891	gl.glPixelStorei(GL_UNPACK_SKIP_IMAGES,  m_subcuboid_z0);
1892	gl.glPixelStorei(GL_UNPACK_SKIP_ROWS,	 m_subcuboid_y0);
1893	gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS,  m_subcuboid_x0);
1894
1895	gl.glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY,
1896							  0,
1897							  m_internalFormat,
1898							  m_subcuboid_w,
1899							  m_subcuboid_h,
1900							  m_subcuboid_d,
1901							  0,
1902							  getImageSize(m_subcuboid_w,
1903										   m_subcuboid_h,
1904										   m_subcuboid_d),
1905							  m_src_data);
1906
1907	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE,	 0);
1908	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH,	 0);
1909	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT,  0);
1910	gl.glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH,	 0);
1911
1912	gl.glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
1913	gl.glPixelStorei(GL_UNPACK_ROW_LENGTH,	 0);
1914	gl.glPixelStorei(GL_UNPACK_SKIP_IMAGES,  0);
1915	gl.glPixelStorei(GL_UNPACK_SKIP_ROWS,	 0);
1916	gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS,  0);
1917}
1918
1919void CompressedTexImage3DCase::createShader (void)
1920{
1921	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1922							m_testCtx.getLog());
1923
1924	const tcu::StringTemplate vs_src (vs_template_src);
1925	const tcu::StringTemplate fs_src (fs_template_src);
1926
1927	std::map<std::string,std::string> params;
1928	params["GLSL_VERSION"]	 = getGLSLVersionDeclaration(m_glsl_version);
1929	params["TEXCOORDS_TYPE"] = "vec3";
1930	params["LAYER"]			 = "uniform int layer;";
1931	params["TEXCOORDS"]		 = "vec3(pos.xy, layer)";
1932	params["SAMPLER_TYPE"]	 = "sampler2DArray";
1933	params["COL_TYPE"]		 = "vec4";
1934
1935	const tcu::StringTemplate fs_condition ("all(lessThan((abs(colour - refcolour)).rgb, vec3(${EPS})))");
1936	std::map<std::string,std::string> fs_condition_params;
1937	fs_condition_params["EPS"] = std::to_string(getEps(m_internalFormat));
1938	params["CONDITION"] = fs_condition.specialize(fs_condition_params);
1939
1940	prog = new glu::ShaderProgram(m_context.getRenderContext(),
1941								  glu::ProgramSources() <<
1942								  glu::VertexSource(vs_src.specialize(params)) <<
1943								  glu::FragmentSource(fs_src.specialize(params)));
1944
1945	if (!prog->isOk())
1946	{
1947		m_testCtx.getLog()
1948			<< tcu::TestLog::Message << ""
1949			<< tcu::TestLog::EndMessage
1950			<< tcu::TestLog::ShaderProgram(false, "")
1951			<< tcu::TestLog::Shader(QP_SHADER_TYPE_VERTEX,
1952									prog->getShaderInfo(glu::SHADERTYPE_VERTEX,
1953														0).source,
1954									false,
1955									prog->getShaderInfo(glu::SHADERTYPE_VERTEX,
1956														0).infoLog)
1957
1958			<< tcu::TestLog::Shader(QP_SHADER_TYPE_FRAGMENT,
1959									prog->getShaderInfo(glu::SHADERTYPE_FRAGMENT,
1960														0).source,
1961									false,
1962									prog->getShaderInfo(glu::SHADERTYPE_FRAGMENT,
1963														0).infoLog)
1964			<< tcu::TestLog::EndShaderProgram;
1965		TCU_FAIL("Shader creation failed");
1966	}
1967
1968	gl.glUseProgram(prog->getProgram());
1969	gl.glUniform1i(gl.glGetUniformLocation(prog->getProgram(), "sampler"), 0);
1970}
1971
1972tcu::Surface CompressedTexImage3DCase::renderToSurf (int layer)
1973{
1974	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
1975							m_testCtx.getLog());
1976
1977	gl.glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
1978	gl.glClear(GL_COLOR_BUFFER_BIT);
1979
1980	static const float vertexPositions[4*3] =
1981	{
1982		-1.0, -1.0, -1.0f,
1983		 1.0, -1.0,	 0.0f,
1984		-1.0,  1.0,	 0.0f,
1985		 1.0,  1.0,	 1.0f,
1986	};
1987
1988	static const deUint16 indices[6] = { 0, 1, 2, 2, 1, 3 };
1989
1990	const glu::VertexArrayBinding attrBindings[] =
1991	{
1992		glu::va::Float("pos", 3, 4, 0, &vertexPositions[0])
1993	};
1994
1995	gl.glViewport(0, 0, m_subcuboid_w, m_subcuboid_h);
1996
1997	gl.glUniform1i(gl.glGetUniformLocation(prog->getProgram(), "layer"), layer);
1998
1999	glw::GLfloat refcols[8] = { 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0 };
2000	glw::GLfloat refcol = refcols[(layer + m_subcuboid_z0 % 8) % 8];
2001
2002	gl.glUniform4f(gl.glGetUniformLocation(prog->getProgram(), "refcolour"),
2003				   refcol, refcol, refcol, 1.0f);
2004
2005	glu::draw(m_context.getRenderContext(),
2006			  prog->getProgram(),
2007			  DE_LENGTH_OF_ARRAY(attrBindings),
2008			  &attrBindings[0],
2009			  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
2010
2011	tcu::Surface dst;
2012	dst.setSize(m_subcuboid_w, m_subcuboid_h);
2013
2014	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
2015
2016	return dst;
2017}
2018
2019void CompressedTexImage3DCase::cleanup (void)
2020{
2021	glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(),
2022							m_testCtx.getLog());
2023
2024	gl.glDeleteTextures(1, &tex);
2025	delete[] m_src_data;
2026	delete prog;
2027}
2028
2029PixelStorageModesTests::PixelStorageModesTests (deqp::Context& context,
2030												glu::GLSLVersion glsl_version)
2031	: TestCaseGroup(context, "pixelstoragemodes", "Pixel Storage Modes Tests")
2032	, m_glsl_version(glsl_version)
2033{
2034}
2035
2036PixelStorageModesTests::~PixelStorageModesTests (void)
2037{
2038}
2039
2040void PixelStorageModesTests::init(void)
2041{
2042	const int cuboid_w = 64;
2043	const int cuboid_h = 64;
2044	const int cuboid_d = 64;
2045	const int subcuboid_w = 32;
2046	const int subcuboid_h = 32;
2047	const int subcuboid_d = 8;
2048
2049	struct
2050	{
2051		const char *name;
2052		deUint32 internalFmt;
2053	} internalFmts[] =
2054	{
2055		{ "r8",			 GL_R8,				  },
2056		{ "r8snorm",	 GL_R8_SNORM,		  },
2057		{ "r16f",		 GL_R16F,			  },
2058		{ "r32f",		 GL_R32F,			  },
2059		{ "r8ui",		 GL_R8UI,			  },
2060		{ "r8i",		 GL_R8I,			  },
2061		{ "r16ui",		 GL_R16UI,			  },
2062		{ "r16i",		 GL_R16I,			  },
2063		{ "r32ui",		 GL_R32UI,			  },
2064		{ "r32i",		 GL_R32I,			  },
2065		{ "rg8",		 GL_RG8,			  },
2066		{ "rg8snorm",	 GL_RG8_SNORM,		  },
2067		{ "rg16f",		 GL_RG16F,			  },
2068		{ "rg32f",		 GL_RG32F,			  },
2069		{ "rg8ui",		 GL_RG8UI,			  },
2070		{ "rg8i",		 GL_RG8I,			  },
2071		{ "rg16ui",		 GL_RG16UI,			  },
2072		{ "rg16i",		 GL_RG16I,			  },
2073		{ "rg32ui",		 GL_RG32UI,			  },
2074		{ "rg32i",		 GL_RG32I,			  },
2075		{ "rgb8",		 GL_RGB8,			  },
2076		{ "rgb565",		 GL_RGB565,			  },
2077		{ "rgb8snorm",	 GL_RGB8_SNORM,		  },
2078		{ "r11g11b10f",	 GL_R11F_G11F_B10F,	  },
2079		{ "rgb16f",		 GL_RGB16F,			  },
2080		{ "rgb32f",		 GL_RGB32F,			  },
2081		{ "rgb8ui",		 GL_RGB8UI,			  },
2082		{ "rgb8i",		 GL_RGB8I,			  },
2083		{ "rgb16ui",	 GL_RGB16UI,		  },
2084		{ "rgb16i",		 GL_RGB16I,			  },
2085		{ "rgb32ui",	 GL_RGB32UI,		  },
2086		{ "rgb32i",		 GL_RGB32I,			  },
2087		{ "rgba8",		 GL_RGBA8,			  },
2088		{ "rgba8snorm",	 GL_RGBA8_SNORM,	  },
2089		{ "rgb5a1",		 GL_RGB5_A1,		  },
2090		{ "rgba4",		 GL_RGBA4,			  },
2091		{ "rgb10a2",	 GL_RGB10_A2,		  },
2092		{ "rgba16f",	 GL_RGBA16F,		  },
2093		{ "rgba32f",	 GL_RGBA32F,		  },
2094		{ "rgba8ui",	 GL_RGBA8UI,		  },
2095		{ "rgba8i",		 GL_RGBA8I,			  },
2096		{ "rgb10a2ui",	 GL_RGB10_A2UI,		  },
2097		{ "rgba16ui",	 GL_RGBA16UI,		  },
2098		{ "rgba16i",	 GL_RGBA16I,		  },
2099		{ "rgba32i",	 GL_RGBA32I,		  },
2100		{ "rgba32ui",	 GL_RGBA32UI,		  },
2101	};
2102
2103	struct
2104	{
2105		const char *name;
2106		deUint32 internalFmt;
2107		int bw;
2108		int bh;
2109		int bd;
2110	} internalFmts_compressed[] =
2111	{
2112		{ "rgb_s3tc_dxt1", GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 1 },
2113		{ "rgba_astc_8x5", GL_COMPRESSED_RGBA_ASTC_8x5_KHR, 8, 5, 1 },
2114	};
2115
2116	tcu::TestCaseGroup* texImage2DGroup = new tcu::TestCaseGroup(m_testCtx,
2117																 "teximage2d",
2118																 "glTexImage2D cases");
2119	addChild(texImage2DGroup);
2120
2121	for (int fmts = 0; fmts < DE_LENGTH_OF_ARRAY(internalFmts); fmts++)
2122	{
2123		tcu::TestCaseGroup* formatsGroup = new tcu::TestCaseGroup(m_testCtx,
2124																  internalFmts[fmts].name,
2125																  "");
2126		texImage2DGroup->addChild(formatsGroup);
2127		int bw = 1;
2128		int bh = 1;
2129		int skip_pixels[3] =
2130			{ 0, bw, bw * (subcuboid_w / (2 * bw)) };
2131		int skip_rows[3] =
2132			{ 0, bh, bh * (subcuboid_h / (2 * bh)) };
2133
2134		for (int r = 0; r < 3; r++)
2135		{
2136			for (int p = r; p < 3; p++)
2137			{
2138				std::string skip_name =
2139					std::to_string(skip_pixels[p]) +
2140					"_" +
2141					std::to_string(skip_rows[r]);
2142				std::string skip_desc =
2143					"Skip " +
2144					std::to_string(skip_pixels[p]) +
2145					" pixels and " +
2146					std::to_string(skip_rows[r]) +
2147					" rows";
2148				formatsGroup->addChild(new TexImage2DCase(m_context,
2149														  skip_name.c_str(),
2150														  skip_desc.c_str(),
2151														  internalFmts[fmts].internalFmt,
2152														  cuboid_w,
2153														  cuboid_h,
2154														  skip_pixels[p],
2155														  skip_rows[r],
2156														  subcuboid_w,
2157														  subcuboid_h,
2158														  m_glsl_version));
2159			}
2160		}
2161	}
2162
2163	tcu::TestCaseGroup* texImage3DGroup = new tcu::TestCaseGroup(m_testCtx,
2164																 "teximage3d",
2165																 "glTexImage3D cases");
2166	addChild(texImage3DGroup);
2167
2168	for (int fmts = 0; fmts < DE_LENGTH_OF_ARRAY(internalFmts); fmts++)
2169	{
2170		tcu::TestCaseGroup* formatsGroup = new tcu::TestCaseGroup(m_testCtx,
2171																  internalFmts[fmts].name,
2172																  "");
2173		texImage3DGroup->addChild(formatsGroup);
2174		int bw = 1;
2175		int bh = 1;
2176		int bd = 1;
2177		int skip_pixels[3] =
2178			{ 0, bw, bw * (subcuboid_w / (2 * bw)) };
2179		int skip_rows[3] =
2180			{ 0, bh, bh * (subcuboid_h / (2 * bh)) };
2181		int skip_images[3] =
2182			{ 0, bd, bd * (subcuboid_d / (2 * bd)) };
2183
2184		for (int i = 0; i < 3; i++)
2185		{
2186			for (int r = i; r < 3; r++)
2187			{
2188				for (int p = r; p < 3; p++)
2189				{
2190					std::string skip_name =
2191						std::to_string(skip_pixels[p]) +
2192						"_" +
2193						std::to_string(skip_rows[r]) +
2194						"_" +
2195						std::to_string(skip_images[i]);
2196					std::string skip_desc =
2197						"Skip " +
2198						std::to_string(skip_pixels[p]) +
2199						" pixels, " +
2200						std::to_string(skip_rows[r]) +
2201						" rows, and " +
2202						std::to_string(skip_images[i]) +
2203						" images";
2204					formatsGroup->addChild(new TexImage3DCase(m_context,
2205															  skip_name.c_str(),
2206															  skip_desc.c_str(),
2207															  internalFmts[fmts].internalFmt,
2208															  cuboid_w,
2209															  cuboid_h,
2210															  cuboid_d,
2211															  skip_pixels[p],
2212															  skip_rows[r],
2213															  skip_images[i],
2214															  subcuboid_w,
2215															  subcuboid_h,
2216															  subcuboid_d,
2217															  m_glsl_version));
2218				}
2219			}
2220		}
2221	}
2222
2223	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2224	{
2225		tcu::TestCaseGroup* compressedTexImage2DGroup =
2226			new tcu::TestCaseGroup(m_testCtx,
2227								   "compressedteximage2d",
2228								   "glCompressedTexImage2D cases");
2229		addChild(compressedTexImage2DGroup);
2230
2231		for (int fmts = 0; fmts < DE_LENGTH_OF_ARRAY(internalFmts_compressed); fmts++)
2232		{
2233			tcu::TestCaseGroup* formatsGroup
2234				= new tcu::TestCaseGroup(m_testCtx,
2235										 internalFmts_compressed[fmts].name,
2236										 "");
2237			compressedTexImage2DGroup->addChild(formatsGroup);
2238			int bw = internalFmts_compressed[fmts].bw;
2239			int bh = internalFmts_compressed[fmts].bh;
2240			int skip_pixels[4] =
2241				{ 0, bw, bw * (subcuboid_w / (2 * bw)), bw * (subcuboid_w / bw) };
2242			int skip_rows[4] =
2243				{ 0, bh, bh * (subcuboid_h / (2 * bh)), bh * (subcuboid_h / bh) };
2244			for (int r = 0; r < 4; r++)
2245			{
2246				for (int p = 0; p < 4; p++)
2247				{
2248					std::string skip_name =
2249						std::to_string(skip_pixels[p]) +
2250						"_" +
2251						std::to_string(skip_rows[r]);
2252					std::string skip_desc =
2253						"Skip " +
2254						std::to_string(skip_pixels[p]) +
2255						" pixels and " +
2256						std::to_string(skip_rows[r]) +
2257						" rows";
2258					formatsGroup->addChild(new CompressedTexImage2DCase(
2259											  m_context,
2260											  skip_name.c_str(),
2261											  skip_desc.c_str(),
2262											  internalFmts_compressed[fmts].internalFmt,
2263											  cuboid_w,
2264											  cuboid_h,
2265											  skip_pixels[p],
2266											  skip_rows[r],
2267											  subcuboid_w,
2268											  subcuboid_h,
2269											  m_glsl_version));
2270				}
2271			}
2272		}
2273
2274		tcu::TestCaseGroup* compressedTexImage3DGroup =
2275			new tcu::TestCaseGroup(m_testCtx,
2276								   "compressedteximage3d",
2277								   "glCompressedTexImage3D cases");
2278		addChild(compressedTexImage3DGroup);
2279
2280		for (int fmts = 0; fmts < DE_LENGTH_OF_ARRAY(internalFmts_compressed); fmts++)
2281		{
2282			tcu::TestCaseGroup* formatsGroup
2283				= new tcu::TestCaseGroup(m_testCtx,
2284										 internalFmts_compressed[fmts].name,
2285										 "");
2286			compressedTexImage3DGroup->addChild(formatsGroup);
2287			int bw = internalFmts_compressed[fmts].bw;
2288			int bh = internalFmts_compressed[fmts].bh;
2289			int bd = internalFmts_compressed[fmts].bd;
2290			int skip_pixels[4] =
2291				{ 0, bw, bw * (subcuboid_w / (2 * bw)), bw * (subcuboid_w / bw) };
2292			int skip_rows[4] =
2293				{ 0, bh, bh * (subcuboid_h / (2 * bh)), bh * (subcuboid_h / bh) };
2294			int skip_images[4] =
2295				{ 0, bd, bd * (subcuboid_d / (2 * bd)), bd * (subcuboid_d / bd) };
2296			for (int i = 0; i < 4; i++)
2297			{
2298				for (int r = 0; r < 4; r++)
2299				{
2300					for (int p = 0; p < 4; p++)
2301					{
2302						std::string skip_name =
2303							std::to_string(skip_pixels[p]) +
2304							"_" +
2305							std::to_string(skip_rows[r]) +
2306							"_" +
2307							std::to_string(skip_images[i]);
2308						std::string skip_desc =
2309							"Skip " +
2310							std::to_string(skip_pixels[p]) +
2311							" pixels, " +
2312							std::to_string(skip_rows[r]) +
2313							" rows, and " +
2314							std::to_string(skip_images[i]) +
2315							" images";
2316						formatsGroup->addChild(new CompressedTexImage3DCase(
2317												  m_context,
2318												  skip_name.c_str(),
2319												  skip_desc.c_str(),
2320												  internalFmts_compressed[fmts].internalFmt,
2321												  cuboid_w,
2322												  cuboid_h,
2323												  cuboid_d,
2324												  skip_pixels[p],
2325												  skip_rows[r],
2326												  skip_images[i],
2327												  subcuboid_w,
2328												  subcuboid_h,
2329												  subcuboid_d,
2330												  m_glsl_version));
2331					}
2332				}
2333			}
2334		}
2335	}
2336}
2337
2338} /* namespace glcts */
2339