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