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 
35 using namespace glw;
36 
37 namespace glcts
38 {
39 
40 union 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 
56 enum 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 
65 enum 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 */
78 struct 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 
101 static 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 
233 struct 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 
244 static 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 
347 static 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 
423 const 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 
448 const 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 
457 const 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 
469 const 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 
483 struct TestArea
484 {
485 	GLsizei left;
486 	GLsizei right;
487 	GLsizei top;
488 	GLsizei bottom;
489 };
490 
491 class TestClampModeForInternalFormat : public deqp::TestCase
492 {
493 public:
494 	/* Public methods */
495 	TestClampModeForInternalFormat(deqp::Context& context, const std::string& name, GLenum internalFormat,
496 								   GLenum clampMode, GLint lodLevel, GLsizei width, GLsizei height);
~TestClampModeForInternalFormat()497 	virtual ~TestClampModeForInternalFormat()
498 	{
499 	}
500 
501 	/* Public methods inherited from TestCase */
502 	virtual tcu::TestNode::IterateResult iterate(void);
503 
504 private:
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 
522 private:
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  **/
TestClampModeForInternalFormat(deqp::Context & context,const std::string & name,GLenum internalFormat,GLenum clampMode,GLint lodLevel,GLsizei width,GLsizei height)535 TestClampModeForInternalFormat::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 
findInternalFormat(GLenum internalformat) const548 const 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 
findFormat(GLenum internalformat) const568 const 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 
isEqual(const GLubyte * color1,const GLubyte * color2,GLubyte tolerance) const576 bool 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  */
fillTextureWithColor(GLubyte * texture_data,GLsizei tex_width,GLsizei tex_height,GLenum internalformat) const597 void 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 
clearTextures(GLenum target,GLsizei width,GLsizei height,GLint lod,GLenum internalformat,GLenum type,GLenum format) const637 void 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 */
calcTextureEpsilon(const GLsizei textureBits[4],GLfloat textureEpsilon[4]) const670 void 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 */
proportion(GLsizei a,GLsizei b,GLsizei c) const728 GLsizei 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  */
verifyClampToEdge(GLubyte * buf,GLsizei width_init,GLsizei height_init,GLsizei width,GLsizei height,GLenum internalformat) const745 bool 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  */
verifyRepeat(GLubyte * buf,GLsizei width,GLsizei height,GLenum internalformat) const838 bool 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  */
verifyMirroredRepeat(GLubyte * buf,GLsizei width,GLsizei height,GLenum internalformat) const921 bool 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 
verifyClampMode(GLubyte * buf,GLsizei width,GLsizei height,GLenum clampMode,GLenum internalformat) const1125 bool 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 **/
iterate(void)1215 tcu::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  */
TextureRepeatModeTests(deqp::Context & context)1340 TextureRepeatModeTests::TextureRepeatModeTests(deqp::Context& context)
1341 	: TestCaseGroup(context, "texture_repeat_mode", "Texture repeat mode tests")
1342 {
1343 }
1344 
1345 /** Initializes the test group contents. */
init()1346 void 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