1 /*
2  * Copyright (c) 2010-2012 VMware, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * on the rights to use, copy, modify, merge, publish, distribute, sub
8  * license, and/or sell copies of the Software, and to permit persons to whom
9  * the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NON-INFRINGEMENT.  IN NO EVENT SHALL VMWARE AND/OR THEIR SUPPLIERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 /**
26  * @file
27  * Tests OpenGL 3.0 integer textures
28  */
29 
30 #include "piglit-util-gl.h"
31 
32 PIGLIT_GL_TEST_CONFIG_BEGIN
33 
34 	config.supports_gl_compat_version = 10;
35 	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
36 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
37 
38 PIGLIT_GL_TEST_CONFIG_END
39 
40 static const char *TestName = "texture-integer";
41 static GLint TexWidth = 16, TexHeight = 16;
42 static GLint BiasUniform = -1, TexUniform = -1;
43 
44 struct format_info
45 {
46 	GLenum IntFormat, BaseFormat;
47 	GLuint BitsPerChannel;
48 	GLboolean Signed;
49 };
50 
51 
52 static const struct format_info Formats[] = {
53 	/* { "GL_RGBA", GL_RGBA, GL_RGBA, 8, GL_FALSE },*/
54 	{ GL_RGBA8I_EXT,   GL_RGBA_INTEGER_EXT, 8,  GL_TRUE  },
55 	{ GL_RGBA8UI_EXT,  GL_RGBA_INTEGER_EXT, 8,  GL_FALSE },
56 	{ GL_RGBA16I_EXT,  GL_RGBA_INTEGER_EXT, 16, GL_TRUE  },
57 	{ GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, 16, GL_FALSE },
58 	{ GL_RGBA32I_EXT,  GL_RGBA_INTEGER_EXT, 32, GL_TRUE  },
59 	{ GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, 32, GL_FALSE },
60 
61 	{ GL_RGB8I_EXT,   GL_RGB_INTEGER_EXT, 8,  GL_TRUE  },
62 	{ GL_RGB8UI_EXT,  GL_RGB_INTEGER_EXT, 8,  GL_FALSE },
63 	{ GL_RGB16I_EXT,  GL_RGB_INTEGER_EXT, 16, GL_TRUE  },
64 	{ GL_RGB16UI_EXT, GL_RGB_INTEGER_EXT, 16, GL_FALSE },
65 	{ GL_RGB32I_EXT,  GL_RGB_INTEGER_EXT, 32, GL_TRUE  },
66 	{ GL_RGB32UI_EXT, GL_RGB_INTEGER_EXT, 32, GL_FALSE },
67 
68 	{ GL_ALPHA8I_EXT,   GL_ALPHA_INTEGER_EXT, 8,  GL_TRUE  },
69 	{ GL_ALPHA8UI_EXT,  GL_ALPHA_INTEGER_EXT, 8,  GL_FALSE },
70 	{ GL_ALPHA16I_EXT,  GL_ALPHA_INTEGER_EXT, 16, GL_TRUE  },
71 	{ GL_ALPHA16UI_EXT, GL_ALPHA_INTEGER_EXT, 16, GL_FALSE },
72 	{ GL_ALPHA32I_EXT,  GL_ALPHA_INTEGER_EXT, 32, GL_TRUE  },
73 	{ GL_ALPHA32UI_EXT, GL_ALPHA_INTEGER_EXT, 32, GL_FALSE },
74 
75 	{ GL_LUMINANCE8I_EXT,   GL_LUMINANCE_INTEGER_EXT, 8,  GL_TRUE  },
76 	{ GL_LUMINANCE8UI_EXT,  GL_LUMINANCE_INTEGER_EXT, 8,  GL_FALSE },
77 	{ GL_LUMINANCE16I_EXT,  GL_LUMINANCE_INTEGER_EXT, 16, GL_TRUE  },
78 	{ GL_LUMINANCE16UI_EXT, GL_LUMINANCE_INTEGER_EXT, 16, GL_FALSE },
79 	{ GL_LUMINANCE32I_EXT,  GL_LUMINANCE_INTEGER_EXT, 32, GL_TRUE  },
80 	{ GL_LUMINANCE32UI_EXT, GL_LUMINANCE_INTEGER_EXT, 32, GL_FALSE },
81 
82 	{ GL_LUMINANCE_ALPHA8I_EXT,   GL_LUMINANCE_ALPHA_INTEGER_EXT, 8,  GL_TRUE  },
83 	{ GL_LUMINANCE_ALPHA8UI_EXT,  GL_LUMINANCE_ALPHA_INTEGER_EXT, 8,  GL_FALSE },
84 	{ GL_LUMINANCE_ALPHA16I_EXT,  GL_LUMINANCE_ALPHA_INTEGER_EXT, 16, GL_TRUE  },
85 	{ GL_LUMINANCE_ALPHA16UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, 16, GL_FALSE },
86 	{ GL_LUMINANCE_ALPHA32I_EXT,  GL_LUMINANCE_ALPHA_INTEGER_EXT, 32, GL_TRUE  },
87 	{ GL_LUMINANCE_ALPHA32UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, 32, GL_FALSE },
88 
89 	{ GL_INTENSITY8I_EXT,   GL_RED_INTEGER_EXT, 8,  GL_TRUE  },
90 	{ GL_INTENSITY8UI_EXT,  GL_RED_INTEGER_EXT, 8,  GL_FALSE },
91 	{ GL_INTENSITY16I_EXT,  GL_RED_INTEGER_EXT, 16, GL_TRUE  },
92 	{ GL_INTENSITY16UI_EXT, GL_RED_INTEGER_EXT, 16, GL_FALSE },
93 	{ GL_INTENSITY32I_EXT,  GL_RED_INTEGER_EXT, 32, GL_TRUE  },
94 	{ GL_INTENSITY32UI_EXT, GL_RED_INTEGER_EXT, 32, GL_FALSE },
95 };
96 
97 
98 /**
99  * The basic idea here is to sample the integer texture and then apply
100  * a bias vector to bring all the color components into the [0,1] range.
101  * One minor issue is that we can't test the full range of 32-bit integer
102  * textures since we cast the int values to floats.  But we test enough of
103  * the range to be confident.
104  */
105 static const char *FragShaderText =
106 	"#version 130 \n"
107 	"uniform vec4 bias; \n"
108 	"uniform isampler2D tex; \n"
109 	"void main() \n"
110 	"{ \n"
111 	"   ivec4 t = texture(tex, gl_TexCoord[0].xy); \n"
112 	"   gl_FragColor = vec4(t) + bias; \n"
113 	"} \n";
114 
115 
116 /**
117  * Return the max texture value that can be represented with the given
118  * integer format.
119  */
120 static int
get_max_val(const struct format_info * info)121 get_max_val(const struct format_info *info)
122 {
123 	int max;
124 
125 	switch (info->BitsPerChannel) {
126 	case 8:
127 		if (info->Signed)
128 			max = 127;
129 		else
130 			max = 255;
131 		break;
132 	case 16:
133 		if (info->Signed)
134 			max = 32767;
135 		else
136 			max = 65535;
137 		break;
138 	case 32:
139 		if (info->Signed)
140 			max = 10*1000; /* don't use 0x8fffffff to avoid overflow issues */
141 		else
142 			max = 20*1000;
143 		break;
144 	default:
145 		assert(!"unexpected bpp");
146 		max = 0;
147 	}
148 
149 	return max;
150 }
151 
152 
153 /**
154  * Return the number of color components in the given format.
155  */
156 static int
num_components(GLenum format)157 num_components(GLenum format)
158 {
159 	switch (format) {
160 	case GL_RGBA:
161 	case GL_RGBA_INTEGER_EXT:
162 		return 4;
163 	case GL_RGB_INTEGER_EXT:
164 		return 3;
165 	case GL_ALPHA_INTEGER_EXT:
166 		return 1;
167 	case GL_LUMINANCE_INTEGER_EXT:
168 		return 1;
169 	case GL_LUMINANCE_ALPHA_INTEGER_EXT:
170 		return 2;
171 	case GL_RED_INTEGER_EXT:
172 		return 1;
173 	default:
174 		assert(!"unexpected format");
175 		return 0;
176 	}
177 }
178 
179 
180 /**
181  * Fill image buffer with given value.
182  */
183 static void
fill_array(int comps,int texels,void * buf,int bpp,const int val[4])184 fill_array(int comps, int texels, void *buf, int bpp, const int val[4])
185 {
186 	int i, j;
187 
188 	switch (bpp) {
189 	case 8:
190 		{
191 			GLubyte *b = (GLubyte *) buf;
192 			for (i = 0; i < texels; i++) {
193 				for (j = 0; j < comps; j++) {
194 					b[i * comps + j] = val[j];
195 				}
196 			}
197 		}
198 		break;
199 	case 16:
200 		{
201 			GLushort *b = (GLushort *) buf;
202 			for (i = 0; i < texels; i++) {
203 				for (j = 0; j < comps; j++) {
204 					b[i * comps + j] = val[j];
205 				}
206 			}
207 		}
208 		break;
209 	case 32:
210 		{
211 			GLuint *b = (GLuint *) buf;
212 			for (i = 0; i < texels; i++) {
213 				for (j = 0; j < comps; j++) {
214 					b[i * comps + j] = val[j];
215 				}
216 			}
217 		}
218 		break;
219 	default:
220 		assert(!"unexpected bpp");
221 	}
222 }
223 
224 
225 static GLenum
get_datatype(const struct format_info * info)226 get_datatype(const struct format_info *info)
227 {
228 	switch (info->BitsPerChannel) {
229 	case 8:
230 		return info->Signed ? GL_BYTE : GL_UNSIGNED_BYTE;
231 	case 16:
232 		return info->Signed ? GL_SHORT : GL_UNSIGNED_SHORT;
233 	case 32:
234 		return info->Signed ? GL_INT : GL_UNSIGNED_INT;
235 	default:
236 		assert(!"unexpected bpp");
237 		return 0;
238 	}
239 }
240 
241 
242 /** \return GL_TRUE for pass, GL_FALSE for fail */
243 static bool
test_format(const struct format_info * info)244 test_format(const struct format_info *info)
245 {
246 	const int max = get_max_val(info);
247 	const int comps = num_components(info->BaseFormat);
248 	const int texels = TexWidth * TexHeight;
249 	const GLenum type = get_datatype(info);
250 	const int w = piglit_width / 10;
251 	const int h = piglit_height / 10;
252 	const float error = 2.0 / 255.0; /* XXX fix */
253 	GLfloat expected[4];
254 	void *buf;
255 	int value[4];
256 	GLfloat result[4], bias[4];
257 	GLint f;
258 
259 	/* pick random texture color */
260 	value[0] = rand() % max;
261 	value[1] = rand() % max;
262 	value[2] = rand() % max;
263 	value[3] = rand() % max;
264 
265 	/* alloc, fill texture image */
266 	buf = malloc(comps * texels * info->BitsPerChannel / 8);
267 	fill_array(comps, texels, buf, info->BitsPerChannel, value);
268 
269 	glTexImage2D(GL_TEXTURE_2D, 0, info->IntFormat, TexWidth, TexHeight, 0,
270 					 info->BaseFormat, type, buf);
271 
272 	/* make sure the teximage call worked */
273 	if (!piglit_check_gl_error(GL_NO_ERROR))
274 		return false;
275 
276 	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &f);
277 
278 	/* setup expected polygon color */
279 	expected[0] = 0.25;
280 	expected[1] = 0.50;
281 	expected[2] = 0.75;
282 	expected[3] = 1.00;
283 
284 	/* need to swizzle things depending on texture format */
285 	switch (info->BaseFormat) {
286 	case GL_RGBA_INTEGER_EXT:
287 		/* nothing */
288 		break;
289 	case GL_RGB_INTEGER_EXT:
290 		value[3] = 0.0;
291 		break;
292 	case GL_ALPHA_INTEGER_EXT:
293 		expected[0] = expected[1] = expected[2] = 0.0;
294 		expected[3] = 0.25;
295 		value[3] = value[0];
296 		value[0] = value[1] = value[2] = 0.0;
297 		break;
298 	case GL_LUMINANCE_INTEGER_EXT:
299 		expected[0] = expected[1] = expected[2] = 0.25;
300 		expected[3] = 1.0;
301 		value[1] = value[2] = value[0];
302 		value[3] = 1.0;
303 		break;
304 	case GL_LUMINANCE_ALPHA_INTEGER_EXT:
305 		expected[0] = expected[1] = expected[2] = 0.25;
306 		value[3] = value[1];
307 		value[1] = value[2] = value[0];
308 		break;
309 	case GL_RED_INTEGER_EXT:
310 		expected[0] = expected[1] = expected[2] = expected[3] = 0.25;
311 		value[1] = value[2] = value[3] = value[0];
312 		break;
313 	default:
314 		;
315 	}
316 
317 	/* compute, set test bias */
318 	bias[0] = expected[0] - value[0];
319 	bias[1] = expected[1] - value[1];
320 	bias[2] = expected[2] - value[2];
321 	bias[3] = expected[3] - value[3];
322 	glUniform4fv(BiasUniform, 1, bias);
323 
324 	/* draw */
325 	glClearColor(0, 1, 1, 0);
326 	glClear(GL_COLOR_BUFFER_BIT);
327 	glBegin(GL_POLYGON);
328 	glTexCoord2f(0, 0);	glVertex2f(0, 0);
329 	glTexCoord2f(1, 0);	glVertex2f(w, 0);
330 	glTexCoord2f(1, 1);	glVertex2f(w, h);
331 	glTexCoord2f(0, 1);	glVertex2f(0, h);
332 	glEnd();
333 
334 	/* test */
335 	glReadPixels(w/2, h/2, 1, 1, GL_RGBA, GL_FLOAT, result);
336 
337 	if (fabsf(result[0] - expected[0]) > error ||
338 		 fabsf(result[1] - expected[1]) > error ||
339 		 fabsf(result[2] - expected[2]) > error ||
340 		 fabsf(result[3] - expected[3]) > error) {
341 		fprintf(stderr, "%s: failure with format %s:\n", TestName,
342 			piglit_get_gl_enum_name(info->IntFormat));
343 		fprintf(stderr, "  texture color = %d, %d, %d, %d\n",
344 				  value[0], value[1], value[2], value[3]);
345 		fprintf(stderr, "  expected color = %g, %g, %g, %g\n",
346 				  expected[0], expected[1], expected[2], expected[3]);
347 		fprintf(stderr, "  result color = %g, %g, %g, %g\n",
348 				  result[0], result[1], result[2], result[3]);
349 		return false;
350 	}
351 
352 	piglit_present_results();
353 
354 	free(buf);
355 
356 	return GL_TRUE;
357 }
358 
359 
360 enum piglit_result
piglit_display(void)361 piglit_display(void)
362 {
363 	int f, i;
364 
365 	for (f = 0; f < ARRAY_SIZE(Formats); f++) {
366 		for (i = 0; i < 5; i++) {
367 			if (!test_format(&Formats[f]))
368 				return PIGLIT_FAIL;
369 		}
370 	}
371 
372 	return PIGLIT_PASS;
373 }
374 
375 
376 void
piglit_init(int argc,char ** argv)377 piglit_init(int argc, char **argv)
378 {
379 	GLuint program;
380         static GLuint tex;
381 
382 	piglit_require_gl_version(30);
383 	piglit_require_GLSL_version(130);
384 
385 	program = piglit_build_simple_program(NULL, FragShaderText);
386 	glUseProgram(program);
387 
388 	BiasUniform = glGetUniformLocation(program, "bias");
389 	TexUniform = glGetUniformLocation(program, "tex");
390 
391 	glUniform1i(TexUniform, 0);  /* tex unit zero */
392 
393 	glGenTextures(1, &tex);
394 	glBindTexture(GL_TEXTURE_2D, tex);
395 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
396 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
397 
398 	piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
399 }
400