1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
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  glcTextureRepeatModeTests.cpp
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24#include "glcTextureRepeatModeTests.hpp"
25#include "deMath.h"
26#include "gluContextInfo.hpp"
27#include "gluDefs.hpp"
28#include "gluShaderProgram.hpp"
29#include "gluStrUtil.hpp"
30#include "glwEnums.hpp"
31#include "glwFunctions.hpp"
32#include "tcuRenderTarget.hpp"
33#include "tcuTestLog.hpp"
34
35using namespace glw;
36
37namespace glcts
38{
39
40union InternalFormatBits {
41	struct Bits
42	{
43		int red;	   /* red bits */
44		int green;	 /* green bits */
45		int blue;	  /* blue bits */
46		int alpha;	 /* alpha bits */
47		int intensity; /* intensity bits */
48		int luminance; /* luminance bits */
49		int depth;	 /* depth bits */
50		int stencil;   /* stencil bits */
51		int exponent;  /* shared exponent bits */
52	} bits;
53	int array[9]; /* all the bits */
54};
55
56enum InternalFormatSamplerType
57{
58	SAMPLER_UNORM = 0, /* unsigned normalized */
59	SAMPLER_NORM,	  /* normalized */
60	SAMPLER_UINT,	  /* unsigned integer */
61	SAMPLER_INT,	   /* integer */
62	SAMPLER_FLOAT	  /* floating-point */
63};
64
65enum InternalFormatFlag
66{
67	NO_FLAG			  = 0,
68	FLAG_PACKED		  = 1,									   /* Packed pixel format. */
69	FLAG_COMPRESSED   = 2,									   /* Compressed format. */
70	FLAG_REQ_RBO_GL42 = 4,									   /* Required RBO & tex format in OpenGL 4.2. */
71	FLAG_REQ_RBO_ES30 = 8,									   /* Required RBO & tex format in OpenGL ES 3.0. */
72	FLAG_REQ_RBO	  = FLAG_REQ_RBO_GL42 | FLAG_REQ_RBO_ES30, /* Required RBO & tex format in both. */
73};
74
75#define MAX_PIXEL_SIZE 16
76
77/* Note that internal representation is in little endian - tests will fail on big endian, in particular RGB565 will fail */
78struct FormatInfo
79{
80	/* internal format, indicating tested format */
81	GLenum internalformat;
82
83	const char* name;
84
85	/* number of bytes per pixel */
86	GLsizei pixelSize;
87
88	/* RGBW colors' representation, specific for each internalformat */
89	GLubyte internalred[MAX_PIXEL_SIZE];
90	GLubyte internalgreen[MAX_PIXEL_SIZE];
91	GLubyte internalblue[MAX_PIXEL_SIZE];
92	GLubyte internalwhite[MAX_PIXEL_SIZE];
93
94	/* RGBW colors' mapped to RGBA, that are read from framebuffer */
95	GLubyte RGBAred[4];
96	GLubyte RGBAgreen[4];
97	GLubyte RGBAblue[4];
98	GLubyte RGBAwhite[4];
99};
100
101static const FormatInfo testedFormats[] = {
102	{
103		GL_R8,
104		"r8",
105		1,
106		{ 0xFF },
107		{ 0xC7 },
108		{ 0x30 },
109		{ 0x00 },
110		/* expected values */
111		{ 0xFF, 0x00, 0x00, 0xFF },
112		{ 0xC7, 0x00, 0x00, 0xFF },
113		{ 0x30, 0x00, 0x00, 0xFF },
114		{ 0x00, 0x00, 0x00, 0xFF },
115	},
116	{
117		GL_RGB565,
118		"rgb565",
119		2,
120		{ 0x00, 0xF8 },
121		{ 0xE0, 0x07 },
122		{ 0x1F, 0x00 },
123		{ 0xFF, 0xFF },
124		/* expected values */
125		{ 0xFF, 0x00, 0x00, 0xFF },
126		{ 0x00, 0xFF, 0x00, 0xFF },
127		{ 0x00, 0x00, 0xFF, 0xFF },
128		{ 0xFF, 0xFF, 0xFF, 0xFF },
129	},
130	{
131		GL_RGB8,
132		"rgb8",
133		3,
134		{ 0xFF, 0x00, 0x00 },
135		{ 0x00, 0xFF, 0x00 },
136		{ 0x00, 0x00, 0xFF },
137		{ 0xFF, 0xFF, 0xFF },
138		/* expected values */
139		{ 0xFF, 0x00, 0x00, 0xFF },
140		{ 0x00, 0xFF, 0x00, 0xFF },
141		{ 0x00, 0x00, 0xFF, 0xFF },
142		{ 0xFF, 0xFF, 0xFF, 0xFF },
143	},
144	{
145		GL_RGB10_A2,
146		"rgb10_a2",
147		4,
148		{ 0xFF, 0x03, 0x00, 0xC0 },
149		{ 0x00, 0xFC, 0x0F, 0xC0 },
150		{ 0x00, 0x00, 0xF0, 0xFF },
151		{ 0xFF, 0xFF, 0xFF, 0xFF },
152		/* expected values */
153		{ 0xFF, 0x00, 0x00, 0xFF },
154		{ 0x00, 0xFF, 0x00, 0xFF },
155		{ 0x00, 0x00, 0xFF, 0xFF },
156		{ 0xFF, 0xFF, 0xFF, 0xFF },
157	},
158	{
159		/* unsigned integer texture formats : require an unsigned texture sampler in the fragment shader */
160		GL_R32UI,
161		"r32ui",
162		4,
163		{ 0xFF, 0x00, 0x00, 0x00 },
164		{ 0x51, 0x00, 0x00, 0x00 },
165		{ 0xF3, 0x00, 0x00, 0x00 },
166		{ 0x00, 0x00, 0x00, 0x00 },
167		/* expected values */
168		{ 0xFF, 0x00, 0x00, 0xFF },
169		{ 0x51, 0x00, 0x00, 0xFF },
170		{ 0xF3, 0x00, 0x00, 0xFF },
171		{ 0x00, 0x00, 0x00, 0xFF },
172	},
173	{
174		GL_RG32UI,
175		"rg32ui",
176		8,
177		{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 },
178		{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF },
179		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
180		{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
181		/* expected values */
182		{ 0xFF, 0x00, 0x00, 0xFF },
183		{ 0x00, 0xFF, 0x00, 0xFF },
184		{ 0x00, 0x00, 0x00, 0xFF },
185		{ 0xFF, 0xFF, 0x00, 0xFF },
186	},
187	{
188		GL_RGBA32UI,
189		"rgba32ui",
190		16,
191		{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF },
192		{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF },
193		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
194		{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
195		/* expected values */
196		{ 0xFF, 0x00, 0x00, 0xFF },
197		{ 0x00, 0xFF, 0x00, 0xFF },
198		{ 0x00, 0x00, 0xFF, 0xFF },
199		{ 0xFF, 0xFF, 0xFF, 0xFF },
200	},
201	{
202		/* DEPTH formats are tested by comparing with reference values hard-coded in shaders */
203		GL_DEPTH_COMPONENT16,
204		"depth_component16",
205		2,
206		{ 0xFF, 0xE8 }, /* ~ 0.91 */
207		{ 0xFF, 0xAB }, /* ~ 0.67 */
208		{ 0x00, 0x78 }, /* ~ 0.46 */
209		{ 0x00, 0x3C }, /* ~ 0.23 */
210		/* expected values */
211		{ 0x00, 0x00, 0x00, 0xff },
212		{ 0x00, 0x00, 0xff, 0xff },
213		{ 0x00, 0xff, 0xff, 0xff },
214		{ 0xff, 0xff, 0xff, 0xff },
215	},
216	{
217		/* little-endian order, so the bytes are in reverse order: stencil first, then depth */
218		GL_DEPTH24_STENCIL8,
219		"depth24_stencil8",
220		4,
221		{ 0x00, 0x00, 0xE8, 0xFF }, /* ~ 0.99 */
222		{ 0x88, 0x00, 0xAB, 0xAF }, /* ~ 0.68 */
223		{ 0xBB, 0x28, 0x55, 0x7F }, /* ~ 0.49 */
224		{ 0xFF, 0x78, 0x80, 0x02 }, /* ~ 0.01 */
225		/* expected values */
226		{ 0x00, 0x00, 0x00, 0xff },
227		{ 0x00, 0x00, 0xff, 0xff },
228		{ 0x00, 0xff, 0xff, 0xff },
229		{ 0xff, 0xff, 0xff, 0xff },
230	}
231};
232
233struct InternalFormat
234{
235	GLenum					  sizedFormat;
236	GLenum					  baseFormat;
237	GLenum					  format;
238	GLenum					  type;
239	InternalFormatSamplerType sampler;
240	InternalFormatBits		  bits;
241	GLuint					  flags; // InternalFormatFlag
242};
243
244static const InternalFormat glInternalFormats[] =
245{
246	{ GL_DEPTH_COMPONENT,	GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,		SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 0,16, 0, NO_FLAG } }, NO_FLAG },
247	{ GL_DEPTH_STENCIL,		GL_DEPTH_STENCIL,   GL_DEPTH_STENCIL,   GL_UNSIGNED_INT,		SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 0,24, 8, NO_FLAG } }, NO_FLAG },
248
249	{ GL_RED,				GL_RED,			GL_RED,				GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
250	{ GL_RG,				GL_RG,			GL_RG,				GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
251
252	// Table 3.12
253	{ GL_R8,				GL_RED,			GL_RED,				GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
254	{ GL_R8_SNORM,			GL_RED,			GL_RED,				GL_BYTE,					SAMPLER_NORM,   { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
255	{ GL_R16,				GL_RED,			GL_RED,				GL_UNSIGNED_SHORT,			SAMPLER_UNORM,  { {16, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
256	{ GL_R16_SNORM,			GL_RED,			GL_RED,				GL_SHORT,					SAMPLER_NORM,   { {16, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
257	{ GL_RG8,				GL_RG,			GL_RG,				GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
258	{ GL_RG8_SNORM,			GL_RG,			GL_RG,				GL_BYTE,					SAMPLER_NORM,   { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
259	{ GL_RG16,				GL_RG,			GL_RG,				GL_UNSIGNED_SHORT,			SAMPLER_UNORM,  { {16,16, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
260	{ GL_RG16_SNORM,		GL_RG,			GL_RG,				GL_SHORT,					SAMPLER_NORM,   { {16,16, 0, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
261	{ GL_R3_G3_B2,			GL_RGB,			GL_RGB,				GL_UNSIGNED_BYTE_3_3_2,		SAMPLER_UNORM,  { { 3, 3, 2, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED },
262	{ GL_RGB4,				GL_RGB,			GL_RGB,				GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 4, 4, 4, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
263	{ GL_RGB5,				GL_RGB,			GL_RGB,				GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 5, 5, 5, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
264	{ GL_RGB565,			GL_RGB,			GL_RGB,				GL_UNSIGNED_SHORT_5_6_5,	SAMPLER_UNORM,  { { 5, 6, 5, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO },
265	{ GL_RGB8,				GL_RGB,			GL_RGB,				GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_ES30 },
266	{ GL_RGB8_SNORM,		GL_RGB,			GL_RGB,				GL_BYTE,					SAMPLER_NORM,   { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
267	{ GL_RGB10,				GL_RGB,			GL_RGB,				GL_UNSIGNED_SHORT,			SAMPLER_UNORM,  { {10,10,10, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
268	{ GL_RGB12,				GL_RGB,			GL_RGB,				GL_UNSIGNED_SHORT,			SAMPLER_UNORM,  { {12,12,12, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
269	{ GL_RGB16,				GL_RGB,			GL_RGB,				GL_UNSIGNED_SHORT,			SAMPLER_UNORM,  { {16,16,16, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
270	{ GL_RGB16_SNORM,		GL_RGB,			GL_RGB,				GL_SHORT,					SAMPLER_NORM,   { {16,16,16, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
271	{ GL_RGBA2,				GL_RGBA,		GL_RGBA,			GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 2, 2, 2, 2, 0, 0, 0, 0, NO_FLAG } }, 0 },
272
273	{ GL_RGBA4,				GL_RGBA,		GL_RGBA,			GL_UNSIGNED_SHORT_4_4_4_4,	SAMPLER_UNORM,  { { 4, 4, 4, 4, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO },
274	{ GL_RGB5_A1,			GL_RGBA,		GL_RGBA,			GL_UNSIGNED_SHORT_5_5_5_1,	SAMPLER_UNORM,  { { 5, 5, 5, 1, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO },
275
276	{ GL_RGBA8,				GL_RGBA,		GL_RGBA,			GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
277	{ GL_RGBA8_SNORM,		GL_RGBA,		GL_RGBA,			GL_BYTE,					SAMPLER_NORM,   { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, 0 },
278
279	{ GL_RGB10_A2,			GL_RGBA,		GL_RGBA,			GL_UNSIGNED_INT_2_10_10_10_REV, SAMPLER_UNORM,  { {10,10,10, 2, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO_GL42 },
280	{ GL_RGB10_A2UI,		GL_RGBA,		GL_RGBA_INTEGER,	GL_UNSIGNED_INT_2_10_10_10_REV, SAMPLER_UINT,   { {10,10,10, 2, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO_GL42 },
281
282	{ GL_RGBA12,			GL_RGBA,		GL_RGBA,			GL_UNSIGNED_SHORT,			SAMPLER_UNORM,  { {12,12,12,12, 0, 0, 0, 0, NO_FLAG } }, 0 },
283	{ GL_RGBA16,			GL_RGBA,		GL_RGBA,			GL_UNSIGNED_SHORT,			SAMPLER_UNORM,  { {16,16,16,16, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
284	{ GL_RGBA16_SNORM,		GL_RGBA,		GL_RGBA,			GL_SHORT,					SAMPLER_NORM,   { {16,16,16,16, 0, 0, 0, 0, NO_FLAG } }, 0 },
285
286	{ GL_SRGB8,				GL_RGB,			GL_RGB,				GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
287	{ GL_SRGB8_ALPHA8,		GL_RGBA,		GL_RGBA,			GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
288
289	{ GL_R16F,				GL_RED,		GL_RED,		GL_HALF_FLOAT,					 SAMPLER_FLOAT,  { {16, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
290	{ GL_RG16F,				GL_RG,		GL_RG,		GL_HALF_FLOAT,					 SAMPLER_FLOAT,  { {16,16, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
291	{ GL_RGB16F,			GL_RGB,		GL_RGB,		GL_HALF_FLOAT,					 SAMPLER_FLOAT,  { {16,16,16, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
292	{ GL_RGBA16F,			GL_RGBA,	GL_RGBA,	GL_HALF_FLOAT,					 SAMPLER_FLOAT,  { {16,16,16,16, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
293	{ GL_R32F,				GL_RED,		GL_RED,		GL_FLOAT,						 SAMPLER_FLOAT,  { {32, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
294	{ GL_RG32F,				GL_RG,		GL_RG,		GL_FLOAT,						 SAMPLER_FLOAT,  { {32,32, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
295	{ GL_RGB32F,			GL_RGB,		GL_RGB,		GL_FLOAT,						 SAMPLER_FLOAT,  { {32,32,32, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
296	{ GL_RGBA32F,			GL_RGBA,	GL_RGBA,	GL_FLOAT,						 SAMPLER_FLOAT,  { {32,32,32,32, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
297	{ GL_R11F_G11F_B10F,	GL_RGB,		GL_RGB,		GL_UNSIGNED_INT_10F_11F_11F_REV, SAMPLER_FLOAT,  { {11,11,10, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO_GL42 },
298
299	{ GL_RGB9_E5,			GL_RGB,		GL_RGB,		GL_UNSIGNED_INT_5_9_9_9_REV,	 SAMPLER_FLOAT,  { { 9, 9, 9, 0, 0, 0, 0, 0, 5 } }, FLAG_PACKED },
300
301	{ GL_R8I,		GL_RED,		GL_RED_INTEGER,	 GL_BYTE,			SAMPLER_INT,	{ { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
302	{ GL_R8UI,		GL_RED,		GL_RED_INTEGER,	 GL_UNSIGNED_BYTE,	SAMPLER_UINT,   { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
303	{ GL_R16I,		GL_RED,		GL_RED_INTEGER,	 GL_SHORT,			SAMPLER_INT,	{ {16, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
304	{ GL_R16UI,		GL_RED,		GL_RED_INTEGER,	 GL_UNSIGNED_SHORT,	SAMPLER_UINT,   { {16, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
305	{ GL_R32I,		GL_RED,		GL_RED_INTEGER,	 GL_INT,			SAMPLER_INT,	{ {32, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
306	{ GL_R32UI,		GL_RED,		GL_RED_INTEGER,	 GL_UNSIGNED_INT,	SAMPLER_UINT,   { {32, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
307	{ GL_RG8I,		GL_RG,		GL_RG_INTEGER,	 GL_BYTE,			SAMPLER_INT,	{ { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
308	{ GL_RG8UI,		GL_RG,		GL_RG_INTEGER,	 GL_UNSIGNED_BYTE,	SAMPLER_UINT,   { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
309	{ GL_RG16I,		GL_RG,		GL_RG_INTEGER,	 GL_SHORT,			SAMPLER_INT,	{ {16,16, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
310	{ GL_RG16UI,	GL_RG,		GL_RG_INTEGER,	 GL_UNSIGNED_SHORT,	SAMPLER_UINT,   { {16,16, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
311	{ GL_RG32I,		GL_RG,		GL_RG_INTEGER,	 GL_INT,			SAMPLER_INT,	{ {32,32, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
312	{ GL_RG32UI,	GL_RG,		GL_RG_INTEGER,	 GL_UNSIGNED_INT,	SAMPLER_UINT,   { {32,32, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
313	{ GL_RGB8I,		GL_RGB,		GL_RGB_INTEGER,	 GL_BYTE,			SAMPLER_INT,	{ { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
314	{ GL_RGB8UI,	GL_RGB,		GL_RGB_INTEGER,	 GL_UNSIGNED_BYTE,	SAMPLER_UINT,   { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
315	{ GL_RGB16I,	GL_RGB,		GL_RGB_INTEGER,	 GL_SHORT,			SAMPLER_INT,	{ {16,16,16, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
316	{ GL_RGB16UI,	GL_RGB,		GL_RGB_INTEGER,	 GL_UNSIGNED_SHORT,	SAMPLER_UINT,   { {16,16,16, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
317	{ GL_RGB32I,	GL_RGB,		GL_RGB_INTEGER,	 GL_INT,			SAMPLER_INT,	{ {32,32,32, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
318	{ GL_RGB32UI,	GL_RGB,		GL_RGB_INTEGER,	 GL_UNSIGNED_INT,	SAMPLER_UINT,   { {32,32,32, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
319	{ GL_RGBA8I,	GL_RGBA,	GL_RGBA_INTEGER, GL_BYTE,			SAMPLER_INT,	{ { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
320	{ GL_RGBA8UI,	GL_RGBA,	GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,	SAMPLER_UINT,   { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
321	{ GL_RGBA16I,	GL_RGBA,	GL_RGBA_INTEGER, GL_SHORT,			SAMPLER_INT,	{ {16,16,16,16, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
322	{ GL_RGBA16UI,	GL_RGBA,	GL_RGBA_INTEGER, GL_UNSIGNED_SHORT,	SAMPLER_UINT,   { {16,16,16,16, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
323	{ GL_RGBA32I,	GL_RGBA,	GL_RGBA_INTEGER, GL_INT,			SAMPLER_INT,	{ {32,32,32,32, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
324	{ GL_RGBA32UI,	GL_RGBA,	GL_RGBA_INTEGER, GL_UNSIGNED_INT,	SAMPLER_UINT,   { {32,32,32,32, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
325
326	// Table 3.13
327	{ GL_DEPTH_COMPONENT16,	 GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,					SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 0,16, 0, NO_FLAG } }, FLAG_REQ_RBO },
328	{ GL_DEPTH_COMPONENT24,	 GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,					SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 0,24, 0, NO_FLAG } }, FLAG_REQ_RBO },
329	{ GL_DEPTH_COMPONENT32,	 GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,					SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 0,32, 0, NO_FLAG } }, 0 },
330	{ GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT,							SAMPLER_FLOAT,  { { 0, 0, 0, 0, 0, 0,32, 0, NO_FLAG } }, FLAG_REQ_RBO },
331	{ GL_DEPTH24_STENCIL8,	 GL_DEPTH_STENCIL,   GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,				SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 0,24, 8, NO_FLAG } }, FLAG_REQ_RBO },
332	{ GL_DEPTH32F_STENCIL8,	 GL_DEPTH_STENCIL,   GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, SAMPLER_FLOAT,  { { 0, 0, 0, 0, 0, 0,32, 8, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO },
333
334	// Table 3.14
335	{ GL_COMPRESSED_RED,			  GL_RED,	GL_RED,	  GL_UNSIGNED_BYTE,   SAMPLER_UNORM,  { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
336	{ GL_COMPRESSED_RG,				  GL_RG,	GL_RG,	  GL_UNSIGNED_BYTE,   SAMPLER_UNORM,  { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
337	{ GL_COMPRESSED_RGB,			  GL_RGB,	GL_RGB,	  GL_UNSIGNED_BYTE,   SAMPLER_UNORM,  { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
338	{ GL_COMPRESSED_RGBA,			  GL_RGBA,	GL_RGBA,  GL_UNSIGNED_BYTE,   SAMPLER_UNORM,  { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
339	{ GL_COMPRESSED_SRGB,			  GL_RGB,	GL_RGB,	  GL_UNSIGNED_BYTE,   SAMPLER_UNORM,  { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
340	{ GL_COMPRESSED_SRGB_ALPHA,		  GL_RGBA,	GL_RGBA,  GL_UNSIGNED_BYTE,   SAMPLER_UNORM,  { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
341	{ GL_COMPRESSED_RED_RGTC1,		  GL_RED,	GL_RED,	  GL_UNSIGNED_BYTE,   SAMPLER_UNORM,  { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
342	{ GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED,	GL_RED,	  GL_BYTE,			  SAMPLER_NORM,   { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
343	{ GL_COMPRESSED_RG_RGTC2,		  GL_RG,	GL_RG,	  GL_UNSIGNED_BYTE,   SAMPLER_UNORM,  { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
344	{ GL_COMPRESSED_SIGNED_RG_RGTC2,  GL_RG,	GL_RG,	  GL_BYTE,			  SAMPLER_NORM,   { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_COMPRESSED },
345};
346
347static const InternalFormat esInternalFormats[] =
348{
349	// Table 3.3
350	{ GL_LUMINANCE,			GL_LUMINANCE,		GL_LUMINANCE,		GL_UNSIGNED_BYTE,	SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 8, 0, 0, NO_FLAG } }, 0 },
351	{ GL_ALPHA,				GL_ALPHA,			GL_ALPHA,			GL_UNSIGNED_BYTE,	SAMPLER_UNORM,  { { 0, 0, 0, 8, 0, 0, 0, 0, NO_FLAG } }, 0 },
352	{ GL_LUMINANCE_ALPHA,	GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,	SAMPLER_UNORM,  { { 0, 0, 0, 8, 0, 8, 0, 0, NO_FLAG } }, 0 },
353
354	{ GL_RGB,				GL_RGB,				GL_RGB,				GL_UNSIGNED_BYTE,	SAMPLER_UNORM,  { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
355	{ GL_RGBA,				GL_RGBA,			GL_RGBA,			GL_UNSIGNED_BYTE,	SAMPLER_UNORM,  { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, 0 },
356
357	// Table 3.12
358	{ GL_R8,				GL_RED,			GL_RED,			GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
359	{ GL_R8_SNORM,			GL_RED,			GL_RED,			GL_BYTE,					SAMPLER_NORM,   { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
360	{ GL_RG8,				GL_RG,			GL_RG,			GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
361	{ GL_RG8_SNORM,			GL_RG,			GL_RG,			GL_BYTE,					SAMPLER_NORM,   { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
362	{ GL_RGB8,				GL_RGB,			GL_RGB,			GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_ES30 },
363	{ GL_RGB8_SNORM,		GL_RGB,			GL_RGB,			GL_BYTE,					SAMPLER_NORM,   { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
364	{ GL_RGB565,			GL_RGB,			GL_RGB,			GL_UNSIGNED_SHORT_5_6_5,	SAMPLER_UNORM,  { { 5, 6, 5, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO },
365
366	{ GL_RGBA4,				GL_RGBA,		GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,  SAMPLER_UNORM,  { { 4, 4, 4, 4, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO },
367	{ GL_RGB5_A1,			GL_RGBA,		GL_RGBA,		GL_UNSIGNED_SHORT_5_5_5_1,  SAMPLER_UNORM,  { { 5, 5, 5, 1, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO },
368
369	{ GL_RGBA8,				GL_RGBA,		GL_RGBA,		GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
370	{ GL_RGBA8_SNORM,		GL_RGBA,		GL_RGBA,		GL_BYTE,					SAMPLER_NORM,   { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, 0 },
371
372	{ GL_RGB10_A2,			GL_RGBA,		GL_RGBA,		 GL_UNSIGNED_INT_2_10_10_10_REV, SAMPLER_UNORM,  { {10,10,10, 2, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO_ES30 },
373	{ GL_RGB10_A2UI,		GL_RGBA,		GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, SAMPLER_UINT,   { {10,10,10, 2, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO_ES30 },
374
375	{ GL_SRGB8,				GL_RGB,			GL_RGB,			GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
376	{ GL_SRGB8_ALPHA8,		GL_RGBA,		GL_RGBA,		GL_UNSIGNED_BYTE,			SAMPLER_UNORM,  { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
377
378	{ GL_R16F,				GL_RED,			GL_RED,			GL_HALF_FLOAT,					 SAMPLER_FLOAT,  { {16, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
379	{ GL_RG16F,				GL_RG,			GL_RG,			GL_HALF_FLOAT,					 SAMPLER_FLOAT,  { {16,16, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
380	{ GL_RGB16F,			GL_RGB,			GL_RGB,			GL_HALF_FLOAT,					 SAMPLER_FLOAT,  { {16,16,16, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
381	{ GL_RGBA16F,			GL_RGBA,		GL_RGBA,		GL_HALF_FLOAT,					 SAMPLER_FLOAT,  { {16,16,16,16, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
382	{ GL_R32F,				GL_RED,			GL_RED,			GL_FLOAT,						 SAMPLER_FLOAT,  { {32, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
383	{ GL_RG32F,				GL_RG,			GL_RG,			GL_FLOAT,						 SAMPLER_FLOAT,  { {32,32, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
384	{ GL_RGB32F,			GL_RGB,			GL_RGB,			GL_FLOAT,						 SAMPLER_FLOAT,  { {32,32,32, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
385	{ GL_RGBA32F,			GL_RGBA,		GL_RGBA,		GL_FLOAT,						 SAMPLER_FLOAT,  { {32,32,32,32, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO_GL42 },
386	{ GL_R11F_G11F_B10F,	GL_RGB,			GL_RGB,			GL_UNSIGNED_INT_10F_11F_11F_REV, SAMPLER_FLOAT,  { {11,11,10, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO_GL42 },
387
388	{ GL_RGB9_E5,			GL_RGB,			GL_RGB,			GL_UNSIGNED_INT_5_9_9_9_REV,	SAMPLER_FLOAT,  { { 9, 9, 9, 0, 0, 0, 0, 0, 5 } }, FLAG_PACKED },
389
390	{ GL_R8I,				GL_RED,			GL_RED_INTEGER,		GL_BYTE,					SAMPLER_INT,	{ { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
391	{ GL_R8UI,				GL_RED,			GL_RED_INTEGER,		GL_UNSIGNED_BYTE,			SAMPLER_UINT,   { { 8, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
392	{ GL_R16I,				GL_RED,			GL_RED_INTEGER,		GL_SHORT,					SAMPLER_INT,	{ {16, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
393	{ GL_R16UI,				GL_RED,			GL_RED_INTEGER,		GL_UNSIGNED_SHORT,			SAMPLER_UINT,   { {16, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
394	{ GL_R32I,				GL_RED,			GL_RED_INTEGER,		GL_INT,						SAMPLER_INT,	{ {32, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
395	{ GL_R32UI,				GL_RED,			GL_RED_INTEGER,		GL_UNSIGNED_INT,			SAMPLER_UINT,   { {32, 0, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
396	{ GL_RG8I,				GL_RG,			GL_RG_INTEGER,		GL_BYTE,					SAMPLER_INT,	{ { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
397	{ GL_RG8UI,				GL_RG,			GL_RG_INTEGER,		GL_UNSIGNED_BYTE,			SAMPLER_UINT,   { { 8, 8, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
398	{ GL_RG16I,				GL_RG,			GL_RG_INTEGER,		GL_SHORT,					SAMPLER_INT,	{ {16,16, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
399	{ GL_RG16UI,			GL_RG,			GL_RG_INTEGER,		GL_UNSIGNED_SHORT,			SAMPLER_UINT,   { {16,16, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
400	{ GL_RG32I,				GL_RG,			GL_RG_INTEGER,		GL_INT,						SAMPLER_INT,	{ {32,32, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
401	{ GL_RG32UI,			GL_RG,			GL_RG_INTEGER,		GL_UNSIGNED_INT,			SAMPLER_UINT,   { {32,32, 0, 0, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
402	{ GL_RGB8I,				GL_RGB,			GL_RGB_INTEGER,		GL_BYTE,					SAMPLER_INT,	{ { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
403	{ GL_RGB8UI,			GL_RGB,			GL_RGB_INTEGER,		GL_UNSIGNED_BYTE,			SAMPLER_UINT,   { { 8, 8, 8, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
404	{ GL_RGB16I,			GL_RGB,			GL_RGB_INTEGER,		GL_SHORT,					SAMPLER_INT,	{ {16,16,16, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
405	{ GL_RGB16UI,			GL_RGB,			GL_RGB_INTEGER,		GL_UNSIGNED_SHORT,			SAMPLER_UINT,   { {16,16,16, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
406	{ GL_RGB32I,			GL_RGB,			GL_RGB_INTEGER,		GL_INT,						SAMPLER_INT,	{ {32,32,32, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
407	{ GL_RGB32UI,			GL_RGB,			GL_RGB_INTEGER,		GL_UNSIGNED_INT,			SAMPLER_UINT,   { {32,32,32, 0, 0, 0, 0, 0, NO_FLAG } }, 0 },
408	{ GL_RGBA8I,			GL_RGBA,		GL_RGBA_INTEGER,	GL_BYTE,					SAMPLER_INT,	{ { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
409	{ GL_RGBA8UI,			GL_RGBA,		GL_RGBA_INTEGER,	GL_UNSIGNED_BYTE,			SAMPLER_UINT,   { { 8, 8, 8, 8, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
410	{ GL_RGBA16I,			GL_RGBA,		GL_RGBA_INTEGER,	GL_SHORT,					SAMPLER_INT,	{ {16,16,16,16, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
411	{ GL_RGBA16UI,			GL_RGBA,		GL_RGBA_INTEGER,	GL_UNSIGNED_SHORT,			SAMPLER_UINT,   { {16,16,16,16, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
412	{ GL_RGBA32I,			GL_RGBA,		GL_RGBA_INTEGER,	GL_INT,						SAMPLER_INT,	{ {32,32,32,32, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
413	{ GL_RGBA32UI,			GL_RGBA,		GL_RGBA_INTEGER,	GL_UNSIGNED_INT,			SAMPLER_UINT,   { {32,32,32,32, 0, 0, 0, 0, NO_FLAG } }, FLAG_REQ_RBO },
414
415	// Table 3.13
416	{ GL_DEPTH_COMPONENT16,	 GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,					SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 0,16, 0, NO_FLAG } }, FLAG_REQ_RBO },
417	{ GL_DEPTH_COMPONENT24,	 GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,					SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 0,24, 0, NO_FLAG } }, FLAG_REQ_RBO },
418	{ GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT,							SAMPLER_FLOAT,  { { 0, 0, 0, 0, 0, 0,32, 0, NO_FLAG } }, FLAG_REQ_RBO },
419	{ GL_DEPTH24_STENCIL8,	 GL_DEPTH_STENCIL,   GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,				SAMPLER_UNORM,  { { 0, 0, 0, 0, 0, 0,24, 8, NO_FLAG } }, FLAG_REQ_RBO },
420	{ GL_DEPTH32F_STENCIL8,	 GL_DEPTH_STENCIL,   GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, SAMPLER_FLOAT,  { { 0, 0, 0, 0, 0, 0,32, 8, NO_FLAG } }, FLAG_PACKED|FLAG_REQ_RBO },
421};
422
423const char* basic_vs = "precision mediump float;\n"
424					   "out vec2 texCoord;\n"
425					   "void main(void)\n"
426					   "{\n"
427					   "	switch(gl_VertexID)\n"
428					   "	{\n"
429					   "		case 0:\n"
430					   "			gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
431					   "			texCoord = vec2(2.0, -1.0);\n"
432					   "			break;\n"
433					   "		case 1:\n"
434					   "			gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
435					   "			texCoord = vec2(2.0, 2.0);\n"
436					   "			break;\n"
437					   "		case 2:\n"
438					   "			gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
439					   "			texCoord = vec2(-1.0, -1.0);\n"
440					   "			break;\n"
441					   "		case 3:\n"
442					   "			gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
443					   "			texCoord = vec2(-1.0, 2.0);\n"
444					   "			break;\n"
445					   "	}\n"
446					   "}";
447
448const char* basic_fs = "precision mediump float;\n"
449					   "uniform sampler2D texture0;\n"
450					   "in vec2 texCoord;\n"
451					   "out vec4 color;\n"
452					   "void main(void)\n"
453					   "{\n"
454					   "	color = texture(texture0, texCoord);\n"
455					   "}";
456
457const char* shadow_fs = "precision mediump float;\n"
458						"uniform mediump sampler2DShadow texture0;\n"
459						"in  vec2 texCoord;\n"
460						"out vec4 color;\n"
461						"void main(void)\n"
462						"{\n"
463						"	float r = texture(texture0, vec3(texCoord.xy, 0.3));\n"
464						"	float g = texture(texture0, vec3(texCoord.xy, 0.5));\n"
465						"	float b = texture(texture0, vec3(texCoord.xy, 0.8));\n"
466						"	color = vec4(r, g, b, 1.0);\n"
467						"}\n";
468
469const char* integer_fs = "precision mediump float;\n"
470						 "uniform mediump usampler2D texture0;\n"
471						 "in vec2 texCoord;\n"
472						 "out vec4 color;\n"
473						 "void main(void)\n"
474						 "{\n"
475						 "	highp uvec4 ci = texture(texture0, texCoord);\n"
476						 "	color = vec4(ci) / 255.0; // we are using an integer texture format - so convert to float\n"
477						 "	if (ci.a > 0u)\n"
478						 "		color.a = 1.0;\n"
479						 "	else\n"
480						 "		color.a = 0.0;\n"
481						 "}";
482
483struct TestArea
484{
485	GLsizei left;
486	GLsizei right;
487	GLsizei top;
488	GLsizei bottom;
489};
490
491class TestClampModeForInternalFormat : public deqp::TestCase
492{
493public:
494	/* Public methods */
495	TestClampModeForInternalFormat(deqp::Context& context, const std::string& name, GLenum internalFormat,
496								   GLenum clampMode, GLint lodLevel, GLsizei width, GLsizei height);
497	virtual ~TestClampModeForInternalFormat()
498	{
499	}
500
501	/* Public methods inherited from TestCase */
502	virtual tcu::TestNode::IterateResult iterate(void);
503
504private:
505	/* Private methods */
506	const FormatInfo* findFormat(GLenum internalformat) const;
507	const InternalFormat& findInternalFormat(GLenum internalformat) const;
508	void clearTextures(GLenum target, GLsizei width, GLsizei height, GLint lod, GLenum internalformat, GLenum type,
509					   GLenum format) const;
510	void fillTextureWithColor(GLubyte* texture_data, GLsizei tex_width, GLsizei tex_height,
511							  GLenum internalformat) const;
512	void calcTextureEpsilon(const GLsizei textureBits[4], GLfloat textureEpsilon[4]) const;
513	GLsizei proportion(GLsizei a, GLsizei b, GLsizei c) const;
514	bool isEqual(const GLubyte* color1, const GLubyte* color2, GLubyte tolerance) const;
515
516	bool verifyClampMode(GLubyte* buf, GLsizei width, GLsizei height, GLenum clampMode, GLenum internalformat) const;
517	bool verifyClampToEdge(GLubyte* buf, GLsizei width_init, GLsizei height_init, GLsizei width, GLsizei height,
518						   GLenum internalformat) const;
519	bool verifyRepeat(GLubyte* buf, GLsizei width, GLsizei height, GLenum internalformat) const;
520	bool verifyMirroredRepeat(GLubyte* buf, GLsizei width, GLsizei height, GLenum internalformat) const;
521
522private:
523	/* Private attributes */
524	GLenum  m_internalFormat;
525	GLenum  m_clampMode;
526	GLint   m_lodLevel;
527	GLsizei m_width;
528	GLsizei m_height;
529};
530
531/** Constructor.
532 *
533 * @param context Rendering context.
534 **/
535TestClampModeForInternalFormat::TestClampModeForInternalFormat(deqp::Context& context, const std::string& name,
536															   GLenum internalFormat, GLenum clampMode, GLint lodLevel,
537															   GLsizei width, GLsizei height)
538	: deqp::TestCase(context, name.c_str(), "")
539	, m_internalFormat(internalFormat)
540	, m_clampMode(clampMode)
541	, m_lodLevel(lodLevel)
542	, m_width(width)
543	, m_height(height)
544{
545	/* Left blank intentionally */
546}
547
548const InternalFormat& TestClampModeForInternalFormat::findInternalFormat(GLenum internalformat) const
549{
550	const InternalFormat* internalFormats	  = glInternalFormats;
551	GLsizei				  internalFormatsCount = DE_LENGTH_OF_ARRAY(glInternalFormats);
552
553	if (glu::isContextTypeES(m_context.getRenderContext().getType()))
554	{
555		internalFormats		 = esInternalFormats;
556		internalFormatsCount = DE_LENGTH_OF_ARRAY(esInternalFormats);
557	}
558
559	for (GLsizei i = 0; i < internalFormatsCount; i++)
560	{
561		if (internalFormats[i].sizedFormat == internalformat)
562			return internalFormats[i];
563	}
564
565	TCU_FAIL("Internal format not found");
566}
567
568const FormatInfo* TestClampModeForInternalFormat::findFormat(GLenum internalformat) const
569{
570	for (GLsizei i = 0; i < DE_LENGTH_OF_ARRAY(testedFormats); i++)
571		if (testedFormats[i].internalformat == internalformat)
572			return &testedFormats[i];
573	return NULL;
574}
575
576bool TestClampModeForInternalFormat::isEqual(const GLubyte* color1, const GLubyte* color2, GLubyte tolerance) const
577{
578	for (int i = 0; i < 4; i++)
579	{
580		if (de::abs((int)color1[i] - (int)color2[i]) > tolerance)
581			return false;
582	}
583	return true;
584}
585
586/** Fill texture with RGBW colors, according to the scheme:
587 *  R R R G G G
588 *  R R R G G G
589 *  R R R G G G
590 *  B B B W W W
591 *  B B B W W W
592 *  B B B W W W
593 *
594 *  NOTE: width of the red and blue rectangles would be less than green and white ones for odd texture's widths
595 *		height of the red and green rectangles would be less than blue and white ones for odd texture's heights
596 */
597void TestClampModeForInternalFormat::fillTextureWithColor(GLubyte* texture_data, GLsizei tex_width, GLsizei tex_height,
598														  GLenum internalformat) const
599{
600	const FormatInfo* testedFormat = findFormat(internalformat);
601	const GLubyte*	red		   = testedFormat->internalred;
602	const GLubyte*	green		   = testedFormat->internalgreen;
603	const GLubyte*	blue		   = testedFormat->internalblue;
604	const GLubyte*	white		   = testedFormat->internalwhite;
605	const GLsizei	 size		   = testedFormat->pixelSize;
606
607	GLint i = 0;
608	GLint j = 0;
609	for (j = 0; j < tex_height / 2; j++)
610	{
611		for (i = 0; i < tex_width / 2; i++)
612		{
613			deMemcpy(texture_data, red, size);
614			texture_data += size;
615		}
616		for (; i < tex_width; i++)
617		{
618			deMemcpy(texture_data, green, size);
619			texture_data += size;
620		}
621	}
622	for (; j < tex_height; j++)
623	{
624		for (i = 0; i < tex_width / 2; i++)
625		{
626			deMemcpy(texture_data, blue, size);
627			texture_data += size;
628		}
629		for (; i < tex_width; i++)
630		{
631			deMemcpy(texture_data, white, size);
632			texture_data += size;
633		}
634	}
635}
636
637void TestClampModeForInternalFormat::clearTextures(GLenum target, GLsizei width, GLsizei height, GLint lod,
638												   GLenum internalformat, GLenum type, GLenum format) const
639{
640	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
641
642	GLint level;
643	for (level = lod; level > 0; level--)
644	{
645		width *= 2;
646		height *= 2;
647	}
648
649	bool				 continueLoop = true;
650	std::vector<GLubyte> tex_buf(width * height * MAX_PIXEL_SIZE, 0);
651	do
652	{
653		if (level != lod)
654			gl.texImage2D(target, level, internalformat, width, height, 0, format, type, &tex_buf[0]);
655		level++;
656
657		continueLoop = !((height == 1) && (width == 1));
658		if (width > 1)
659			width /= 2;
660		if (height > 1)
661			height /= 2;
662	} while (continueLoop);
663}
664
665/* Calculate error epsilons to the least accurate of either
666** frame buffer or texture precision. RGBA epsilons are
667** returned in textureEpsilon[]. target must be a valid
668** texture target.
669*/
670void TestClampModeForInternalFormat::calcTextureEpsilon(const GLsizei textureBits[4], GLfloat textureEpsilon[4]) const
671{
672	GLint i, bits;
673	GLint bufferBits[4];
674
675	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
676	gl.getIntegerv(GL_RED_BITS, &bufferBits[0]);
677	gl.getIntegerv(GL_GREEN_BITS, &bufferBits[1]);
678	gl.getIntegerv(GL_BLUE_BITS, &bufferBits[2]);
679	gl.getIntegerv(GL_ALPHA_BITS, &bufferBits[3]);
680
681	for (i = 0; i < 4; i++)
682	{
683
684		if (textureBits[i] == 0)
685		{
686			/* 'exact' */
687			bits = 1000;
688		}
689		else
690		{
691			bits = textureBits[i];
692		}
693
694		/* Some tests fail on RGB10_A2 pixelformat, because framebuffer precision calculated here is 10-bit, but these tests use 8-bit data types
695		   for pixel transfers and 8-bit textures. Because of that, the required precision is limited to 8-bit only. */
696		if (bits > 8)
697		{
698			bits = 8;
699		}
700
701		/* frame buffer bits */
702		if (bits > bufferBits[i])
703		{
704			bits = bufferBits[i];
705		}
706
707		if (bits == 0)
708		{
709			/* infinity */
710			textureEpsilon[i] = 2.0f;
711		}
712		else
713		{
714			const float zeroEpsilon = deFloatLdExp(1.0f, -13);
715			textureEpsilon[i]		= (1.0f / (deFloatLdExp(1.0f, bits) - 1.0f)) + zeroEpsilon;
716			textureEpsilon[i]		= (float)deMin(1.0f, textureEpsilon[i]);
717		}
718
719		/* If we have 8 bits framebuffer, we should hit the right value within one intensity level. */
720		if (bits == 8 && bufferBits[i] != 0)
721		{
722			textureEpsilon[i] /= 2.0;
723		}
724	}
725}
726
727/* calculate (a * b) / c with rounding */
728GLsizei TestClampModeForInternalFormat::proportion(GLsizei a, GLsizei b, GLsizei c) const
729{
730	float result = (float)a * b;
731	return (GLsizei)(0.5f + result / c);
732}
733
734/* check out the read-back values for GL_CLAMP_TO_EDGE mode
735 * r r r g g g
736 * r r r g g g
737 * r r R G g g
738 * b b B W w w
739 * b b b w w w
740 * b b b w w w
741
742   width_init, height_init arguments refer to the basic pattern texture, which describes proportions
743   between colors in the rendered rectangle (tex_width, tex_height)
744 */
745bool TestClampModeForInternalFormat::verifyClampToEdge(GLubyte* buf, GLsizei width_init, GLsizei height_init,
746													   GLsizei width, GLsizei height, GLenum internalformat) const
747{
748	GLint			  i, h;
749	const FormatInfo* testedFormat = findFormat(internalformat);
750	const GLubyte*	red		   = testedFormat->RGBAred;
751	const GLubyte*	green		   = testedFormat->RGBAgreen;
752	const GLubyte*	blue		   = testedFormat->RGBAblue;
753	const GLubyte*	white		   = testedFormat->RGBAwhite;
754	const GLsizei	 size		   = 4;
755	const GLsizei	 skip		   = 6;
756
757	GLsizei red_w   = proportion(width, width_init / 2, width_init);
758	GLsizei red_h   = proportion(height, height_init / 2, height_init);
759	GLsizei bits[4] = { 8, 8, 8, 8 };
760	GLfloat epsilonf[4];
761	GLubyte epsilons[4];
762
763	TestArea check_area = { 0, width, 0, height };
764
765	calcTextureEpsilon(bits, epsilonf);
766	for (i = 0; i < 4; ++i)
767	{
768		epsilons[i] = (GLubyte)(epsilonf[i] * 255.0f);
769	}
770
771	for (h = 0; h < red_h - skip / 2; h++)
772	{
773		for (i = 0; i < red_w - skip / 2; i++)
774		{
775			/* skip over corner pixel to avoid issues with mipmap selection */
776			if (i >= check_area.left || h >= check_area.top)
777				if (!isEqual(buf, red, epsilons[0]))
778					TCU_FAIL("verifyClampToEdge failed");
779			buf += size;
780		}
781
782		/* skip over border pixels to avoid issues with rounding */
783		i += skip;
784		buf += skip * size;
785
786		for (; i < width; i++)
787		{
788			/* skip over corner pixel to avoid issues with mipmap selection */
789			if (i < check_area.right || h >= check_area.top)
790				if (!isEqual(buf, green, epsilons[1]))
791					TCU_FAIL("verifyClampToEdge failed");
792			buf += size;
793		}
794	}
795
796	/* skip over border pixels to avoid issues with rounding */
797	h += skip;
798	buf += skip * width * size;
799
800	for (; h < height; h++)
801	{
802		for (i = 0; i < red_w - skip / 2; i++)
803		{
804			/* skip over corner pixel to avoid issues with mipmap selection */
805			if (i >= check_area.left || h < check_area.bottom)
806				if (!isEqual(buf, blue, epsilons[2]))
807					TCU_FAIL("verifyClampToEdge failed");
808			buf += size;
809		}
810
811		/* skip over border pixels to avoid issues with rounding */
812		i += skip;
813		buf += skip * size;
814
815		for (; i < width; i++)
816		{
817			/* skip over corner pixel to avoid issues with mipmap selection */
818			if (i < check_area.right || h < check_area.bottom)
819				if (!isEqual(buf, white, epsilons[0]))
820					TCU_FAIL("verifyClampToEdge failed");
821			buf += size;
822		}
823	}
824
825	m_context.getTestContext().getLog() << tcu::TestLog::Message << " verifyClampToEdge succeeded."
826										<< tcu::TestLog::EndMessage;
827	return true;
828}
829
830/* check out the read-back values for GL_REPEAT mode
831 * r g r g r g
832 * b w b w b w
833 * r g R G r g
834 * b w B W b w
835 * r g r g r g
836 * b w b w b w
837 */
838bool TestClampModeForInternalFormat::verifyRepeat(GLubyte* buf, GLsizei width, GLsizei height,
839												  GLenum internalformat) const
840{
841	GLint			  i, j, g, h;
842	const FormatInfo* testedFormat = findFormat(internalformat);
843
844	const GLubyte* red		 = testedFormat->RGBAred;
845	const GLubyte* green	 = testedFormat->RGBAgreen;
846	const GLubyte* blue		 = testedFormat->RGBAblue;
847	const GLubyte* white	 = testedFormat->RGBAwhite;
848	const GLsizei  size		 = 4;
849	const GLubyte  tolerance = 0;
850
851	GLsizei tex_w = width / 3;
852	GLsizei tex_h = height / 3;
853
854	GLsizei red_w = tex_w / 2;
855	GLsizei red_h = tex_h / 2;
856
857	GLsizei green_w = tex_w - red_w;
858
859	GLsizei blue_w = red_w;
860	GLsizei blue_h = tex_h - red_h;
861
862	GLsizei white_w = green_w;
863
864	for (g = 0; g < 3; g++)
865	{
866		for (h = 0; h < red_h; h++)
867		{
868			for (j = 0; j < 3; j++)
869			{
870				for (i = 0; i < red_w; i++)
871				{
872					if (!isEqual(buf, red, tolerance))
873						TCU_FAIL("verifyRepeat failed");
874
875					buf += size;
876				}
877				for (i = 0; i < green_w; i++)
878				{
879					if (!isEqual(buf, green, tolerance))
880						TCU_FAIL("verifyRepeat failed");
881
882					buf += size;
883				}
884			}
885		}
886		for (h = 0; h < blue_h; h++)
887		{
888			for (j = 0; j < 3; j++)
889			{
890				for (i = 0; i < blue_w; i++)
891				{
892					if (!isEqual(buf, blue, tolerance))
893						TCU_FAIL("verifyRepeat failed");
894
895					buf += size;
896				}
897				for (i = 0; i < white_w; i++)
898				{
899					if (!isEqual(buf, white, tolerance))
900						TCU_FAIL("verifyRepeat failed");
901
902					buf += size;
903				}
904			}
905		}
906	}
907
908	m_context.getTestContext().getLog() << tcu::TestLog::Message << " verifyRepeat succeeded."
909										<< tcu::TestLog::EndMessage;
910	return true;
911}
912
913/* check out the read-back values for GL_MIRRORED_REPEAT mode
914 * w b b w w b
915 * g r r g g r
916 * r g R G r g
917 * w b B W w b
918 * w b b w w b
919 * g r r g g r
920 */
921bool TestClampModeForInternalFormat::verifyMirroredRepeat(GLubyte* buf, GLsizei width, GLsizei height,
922														  GLenum internalformat) const
923{
924	GLint			  i, j, g, h;
925	const FormatInfo* testedFormat = findFormat(internalformat);
926
927	const GLubyte* red   = testedFormat->RGBAred;
928	const GLubyte* green = testedFormat->RGBAgreen;
929	const GLubyte* blue  = testedFormat->RGBAblue;
930	const GLubyte* white = testedFormat->RGBAwhite;
931
932	const GLsizei size		= 4;
933	const GLubyte tolerance = 0;
934
935	GLsizei tex_w = width / 3;
936	GLsizei tex_h = height / 3;
937
938	GLsizei red_w = tex_w / 2;
939	GLsizei red_h = tex_h / 2;
940
941	GLsizei green_w = tex_w - red_w;
942	GLsizei green_h = red_h;
943
944	GLsizei blue_w = red_w;
945	GLsizei blue_h = tex_h - red_h;
946
947	GLsizei white_w = green_w;
948	GLsizei white_h = blue_h;
949
950	for (g = 0; g < 3; g++)
951	{
952		if (g % 2 == 0)
953		{
954			for (h = 0; h < white_h; h++)
955			{
956				for (j = 0; j < 3; j++)
957				{
958					if (j % 2 == 0)
959					{
960						for (i = 0; i < white_w; i++)
961						{
962							if (!isEqual(buf, white, tolerance))
963								TCU_FAIL("verifyMirroredRepeat failed");
964
965							buf += size;
966						}
967						for (i = 0; i < blue_w; i++)
968						{
969							if (!isEqual(buf, blue, tolerance))
970								TCU_FAIL("verifyMirroredRepeat failed");
971
972							buf += size;
973						}
974					}
975					else
976					{
977						for (i = 0; i < blue_w; i++)
978						{
979							if (!isEqual(buf, blue, tolerance))
980								TCU_FAIL("verifyMirroredRepeat failed");
981
982							buf += size;
983						}
984						for (i = 0; i < white_w; i++)
985						{
986							if (!isEqual(buf, white, tolerance))
987								TCU_FAIL("verifyMirroredRepeat failed");
988
989							buf += size;
990						}
991					}
992				}
993			}
994			for (h = 0; h < green_h; h++)
995			{
996				for (j = 0; j < 3; j++)
997				{
998					if (j % 2 == 0)
999					{
1000						for (i = 0; i < green_w; i++)
1001						{
1002							if (!isEqual(buf, green, tolerance))
1003								TCU_FAIL("verifyMirroredRepeat failed");
1004
1005							buf += size;
1006						}
1007						for (i = 0; i < red_w; i++)
1008						{
1009							if (!isEqual(buf, red, tolerance))
1010								TCU_FAIL("verifyMirroredRepeat failed");
1011
1012							buf += size;
1013						}
1014					}
1015					else
1016					{
1017						for (i = 0; i < red_w; i++)
1018						{
1019							if (!isEqual(buf, red, tolerance))
1020								TCU_FAIL("verifyMirroredRepeat failed");
1021
1022							buf += size;
1023						}
1024						for (i = 0; i < green_w; i++)
1025						{
1026							if (!isEqual(buf, green, tolerance))
1027								TCU_FAIL("verifyMirroredRepeat failed");
1028
1029							buf += size;
1030						}
1031					}
1032				}
1033			}
1034		}
1035		else
1036		{
1037			for (h = 0; h < green_h; h++)
1038			{
1039				for (j = 0; j < 3; j++)
1040				{
1041					if (j % 2 == 0)
1042					{
1043						for (i = 0; i < green_w; i++)
1044						{
1045							if (!isEqual(buf, green, tolerance))
1046								TCU_FAIL("verifyMirroredRepeat failed");
1047
1048							buf += size;
1049						}
1050						for (i = 0; i < red_w; i++)
1051						{
1052							if (!isEqual(buf, red, tolerance))
1053								TCU_FAIL("verifyMirroredRepeat failed");
1054
1055							buf += size;
1056						}
1057					}
1058					else
1059					{
1060						for (i = 0; i < red_w; i++)
1061						{
1062							if (!isEqual(buf, red, tolerance))
1063								TCU_FAIL("verifyMirroredRepeat failed");
1064
1065							buf += size;
1066						}
1067						for (i = 0; i < green_w; i++)
1068						{
1069							if (!isEqual(buf, green, tolerance))
1070								TCU_FAIL("verifyMirroredRepeat failed");
1071
1072							buf += size;
1073						}
1074					}
1075				}
1076			}
1077			for (h = 0; h < white_h; h++)
1078			{
1079				for (j = 0; j < 3; j++)
1080				{
1081					if (j % 2 == 0)
1082					{
1083						for (i = 0; i < white_w; i++)
1084						{
1085							if (!isEqual(buf, white, tolerance))
1086								TCU_FAIL("verifyMirroredRepeat failed");
1087
1088							buf += size;
1089						}
1090						for (i = 0; i < blue_w; i++)
1091						{
1092							if (!isEqual(buf, blue, tolerance))
1093								TCU_FAIL("verifyMirroredRepeat failed");
1094
1095							buf += size;
1096						}
1097					}
1098					else
1099					{
1100						for (i = 0; i < blue_w; i++)
1101						{
1102							if (!isEqual(buf, blue, tolerance))
1103								TCU_FAIL("verifyMirroredRepeat failed");
1104
1105							buf += size;
1106						}
1107						for (i = 0; i < white_w; i++)
1108						{
1109							if (!isEqual(buf, white, tolerance))
1110								TCU_FAIL("verifyMirroredRepeat failed");
1111
1112							buf += size;
1113						}
1114					}
1115				}
1116			}
1117		}
1118	}
1119
1120	m_context.getTestContext().getLog() << tcu::TestLog::Message << " verifyMirroredRepeat succeeded."
1121										<< tcu::TestLog::EndMessage;
1122	return true;
1123}
1124
1125bool TestClampModeForInternalFormat::verifyClampMode(GLubyte* buf, GLsizei width, GLsizei height, GLenum clampMode,
1126													 GLenum internalformat) const
1127{
1128	switch (clampMode)
1129	{
1130	case GL_CLAMP_TO_EDGE:
1131		return verifyClampToEdge(buf, width, height, width, height, internalformat);
1132	case GL_REPEAT:
1133		return verifyRepeat(buf, width, height, internalformat);
1134	case GL_MIRRORED_REPEAT:
1135		return verifyMirroredRepeat(buf, width, height, internalformat);
1136	}
1137	return false;
1138}
1139
1140/** Execute test
1141 *
1142 * Upload the texture, set up a quad 3 times the size of the
1143 * texture. Coordinates should be integers to avoid spatial rounding
1144 * differences. Set texture coordinates as shown below.
1145 *
1146 * (-1,  2, 0) --- (2,  2, 0)
1147 * |						|
1148 * |						|
1149 * (-1, -1, 0) --- (2, -1, 0)
1150 *
1151 * Set TEXTURE_MIN_FILTER for the texture to NEAREST_MIPMAP_NEAREST.
1152 *
1153 * Repeat the test for each repeat mode, i.e., set the repeat mode to
1154 * one of CLAMP_TO_EDGE, REPEAT, and MIRRORED_REPEAT for both S and
1155 * T, depending on the iteration.
1156 *
1157 * For vertex shader, just pass on the vertices and texture
1158 * coordinates for interpolation. For fragment shader, look up the
1159 * fragment corresponding to given texture coordinates.
1160 *
1161 * Render the quad.
1162 *
1163 * Read back the pixels covering the quad.
1164 *
1165 * For CLAMP_TO_EDGE result should be (Each character has dimension
1166 * half the original texture, original texture in capitals):
1167 *
1168 * rrrggg
1169 * rrrggg
1170 * rrRGgg
1171 * bbBWww
1172 * bbbwww
1173 * bbbwww
1174 *
1175 * For REPEAT:
1176 *
1177 * rgrgrg
1178 * bwbwbw
1179 * rgRGrg
1180 * bwBWbw
1181 * rgrgrg
1182 * bwbwbw
1183 *
1184 * For MIRRORED_REPEAT
1185 *
1186 * wbbwwb
1187 * grrggr
1188 * grRGgr
1189 * wbBWwb
1190 * wbbwwb
1191 * grrggr
1192 *
1193 * If implementation under test is for OpenGL 3.2 Core specification,
1194 * the test includes repeat mode of CLAMP_TO_BORDER. For this case,
1195 * the TEXTURE_BORDER_COLOR is set to black (0, 0, 0, 1) (RGBA). Then
1196 * the result will be (0 meaning black):
1197 *
1198 * 000000
1199 * 000000
1200 * 00RG00
1201 * 00BW00
1202 * 000000
1203 * 000000
1204 *
1205 * Procedure:
1206 * - allocate large enough memory buffer for the texture data - tex_width * tex_height * tex_depth * MAX_PIXEL_SIZE
1207 * - fill the buffer with the pattern
1208 * - upload the texture with glTexImage2D() to the requested level
1209 * - upload black texture to other LOD levels
1210 * - render a quad with size matching the texture LOD level
1211 * - read back pixels
1212 * - verify the results
1213 * - free the buffer
1214**/
1215tcu::TestNode::IterateResult TestClampModeForInternalFormat::iterate(void)
1216{
1217	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1218	m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1219
1220	/* Retrieve properties of the tested format */
1221	const InternalFormat& internalFormatStruct = findInternalFormat(m_internalFormat);
1222	GLenum				  format			   = internalFormatStruct.format;
1223	GLenum				  type				   = internalFormatStruct.type;
1224	GLenum				  internalformat	   = internalFormatStruct.sizedFormat;
1225	GLenum				  sampler			   = internalFormatStruct.sampler;
1226	GLsizei				  viewWidth			   = 3 * m_width;
1227	GLsizei				  viewHeight		   = 3 * m_height;
1228
1229	/* Allocate buffers for texture data */
1230	GLsizei				 resultTextureSize = viewWidth * viewHeight;
1231	std::vector<GLubyte> textureData(resultTextureSize * MAX_PIXEL_SIZE, 0);
1232	std::fill(textureData.begin(), textureData.end(), 0);
1233
1234	/* Set pixel storage modes */
1235	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
1236	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1237
1238	/* Generate and bind the texture object that will store test result*/
1239	GLuint resultTextureId;
1240	gl.genTextures(1, &resultTextureId);
1241	gl.bindTexture(GL_TEXTURE_2D, resultTextureId);
1242	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1243	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1244	gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, viewWidth, viewHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &textureData[0]);
1245
1246	/* Reuse textureData buffer to initialize source texture.
1247	 * Fill the buffer according to the color scheme */
1248	fillTextureWithColor(&textureData[0], m_width, m_height, internalformat);
1249
1250	/* Generate and bind the texture object that will store color scheme*/
1251	GLuint sourceTextureId;
1252	gl.genTextures(1, &sourceTextureId);
1253	gl.bindTexture(GL_TEXTURE_2D, sourceTextureId);
1254	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1255	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1256	gl.texImage2D(GL_TEXTURE_2D, m_lodLevel, internalformat, m_width, m_height, 0, format, type, &textureData[0]);
1257
1258	/* Set compare function used by shadow samplers */
1259	if ((GL_DEPTH_COMPONENT == format) || (GL_DEPTH_STENCIL == format))
1260	{
1261		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1262		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GEQUAL);
1263	}
1264
1265	/* Clear the other source texture levels with black */
1266	clearTextures(GL_TEXTURE_2D, m_width, m_height, m_lodLevel, internalformat, type, format);
1267
1268	/* Create and bind the FBO */
1269	GLuint fbId;
1270	gl.genFramebuffers(1, &fbId);
1271	gl.bindFramebuffer(GL_FRAMEBUFFER, fbId);
1272	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resultTextureId, 0);
1273
1274	/* Construct shaders */
1275	glu::ContextType contextType = m_context.getRenderContext().getType();
1276	glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType);
1277	std::string		 version	 = glu::getGLSLVersionDeclaration(glslVersion) + std::string("\n");
1278	std::string		 vs			 = version + basic_vs;
1279	std::string		 fs			 = version;
1280	if ((GL_DEPTH_COMPONENT == format) || (GL_DEPTH_STENCIL == format))
1281		fs += shadow_fs;
1282	else if ((SAMPLER_UINT == sampler) || (SAMPLER_INT == sampler))
1283		fs += integer_fs;
1284	else
1285		fs += basic_fs;
1286	glu::ProgramSources sources = glu::makeVtxFragSources(vs, fs);
1287
1288	/* Create program object */
1289	glu::ShaderProgram program(m_context.getRenderContext(), sources);
1290	if (!program.isOk())
1291		TCU_FAIL("Compile failed");
1292	GLint programId		  = program.getProgram();
1293	GLint samplerLocation = gl.getUniformLocation(programId, "texture0");
1294	if (-1 == samplerLocation)
1295		TCU_FAIL("Fragment shader does not have texture0 input.");
1296	gl.useProgram(programId);
1297	gl.uniform1i(samplerLocation, 0);
1298
1299	m_context.getTestContext().getLog() << tcu::TestLog::Message << "NPOT [" << m_internalFormat << "] (" << viewWidth
1300										<< " x " << viewHeight << "), Level: " << m_lodLevel
1301										<< tcu::TestLog::EndMessage;
1302
1303	/* Set the wrap parameters for texture coordinates s and t to the current clamp mode */
1304	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_clampMode);
1305	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_clampMode);
1306
1307	/* Set viewport's width and height based on an overview */
1308	gl.viewport(0, 0, viewWidth, viewHeight);
1309
1310	/* Draw rectangle */
1311	GLuint vaoId;
1312	gl.genVertexArrays(1, &vaoId);
1313	gl.bindVertexArray(vaoId);
1314	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
1315	gl.bindVertexArray(0);
1316	gl.deleteVertexArrays(1, &vaoId);
1317
1318	/* Read back pixels and verify that they have the proper values */
1319	std::vector<GLubyte> buffer(resultTextureSize * 4, 0);
1320	gl.readPixels(0, 0, viewWidth, viewHeight, GL_RGBA, GL_UNSIGNED_BYTE, (void*)&(buffer[0]));
1321	if (verifyClampMode(&buffer[0], viewWidth, viewHeight, m_clampMode, internalformat))
1322		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1323
1324	/* Cleanup */
1325	gl.bindTexture(GL_TEXTURE_2D, 0);
1326	gl.deleteTextures(1, &resultTextureId);
1327	gl.deleteTextures(1, &sourceTextureId);
1328	gl.bindFramebuffer(GL_FRAMEBUFFER, fbId);
1329	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
1330	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1331	gl.deleteFramebuffers(1, &fbId);
1332
1333	return STOP;
1334}
1335
1336/** Constructor.
1337 *
1338 *  @param context Rendering context.
1339 */
1340TextureRepeatModeTests::TextureRepeatModeTests(deqp::Context& context)
1341	: TestCaseGroup(context, "texture_repeat_mode", "Texture repeat mode tests")
1342{
1343}
1344
1345/** Initializes the test group contents. */
1346void TextureRepeatModeTests::init()
1347{
1348	/* Texture sizes to test */
1349	const struct TexSize
1350	{
1351		GLsizei width;
1352		GLsizei height;
1353	} textureSizes[] = {
1354		{ 49, 23 }, { 11, 131 },
1355	};
1356
1357	/* LOD levels to test */
1358	const GLint levelsOfDetail[] = { 0, 1, 2 };
1359
1360	for (GLint sizeIndex = 0; sizeIndex < DE_LENGTH_OF_ARRAY(textureSizes); sizeIndex++)
1361	{
1362		const TexSize& ts = textureSizes[sizeIndex];
1363		for (GLint formatIndex = 0; formatIndex < DE_LENGTH_OF_ARRAY(testedFormats); formatIndex++)
1364		{
1365			const FormatInfo& formatInfo	 = testedFormats[formatIndex];
1366			GLenum			  internalFormat = formatInfo.internalformat;
1367			for (GLsizei lodIndex = 0; lodIndex < DE_LENGTH_OF_ARRAY(levelsOfDetail); lodIndex++)
1368			{
1369				GLint			  lod = levelsOfDetail[lodIndex];
1370				std::stringstream testBaseName;
1371				testBaseName << formatInfo.name << "_" << ts.width << "x" << ts.height << "_" << lod << "_";
1372				std::string names[] = { testBaseName.str() + "clamp_to_edge", testBaseName.str() + "repeat",
1373										testBaseName.str() + "mirrored_repeat" };
1374				addChild(new TestClampModeForInternalFormat(m_context, names[0], internalFormat, GL_CLAMP_TO_EDGE, lod,
1375															ts.width, ts.height));
1376				addChild(new TestClampModeForInternalFormat(m_context, names[1], internalFormat, GL_REPEAT, lod,
1377															ts.width, ts.height));
1378				addChild(new TestClampModeForInternalFormat(m_context, names[2], internalFormat, GL_MIRRORED_REPEAT,
1379															lod, ts.width, ts.height));
1380			}
1381		}
1382	}
1383}
1384} /* glcts namespace */
1385