ARB_ubo/referenced-by-shader: pass if shader compiler moves UBOs between shaders
[piglit.git] / tests / spec / arb_direct_state_access / gettextureimage-formats.c
blob168c78a61fe7460f8504ac9203bad52400662ffd
1 /*
2 * Copyright (c) 2011 VMware, Inc.
3 * Copyright (c) 2014 Intel Corporation.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NON-INFRINGEMENT. IN NO EVENT SHALL VMWARE AND/OR THEIR SUPPLIERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
27 /**
28 * @file gettextureimage-formats.c
32 #include "piglit-util-gl.h"
33 #include "../fbo/fbo-formats.h"
34 #include "dsa-utils.h"
36 PIGLIT_GL_TEST_CONFIG_BEGIN
38 config.supports_gl_compat_version = 20;
40 config.window_width = 600;
41 config.window_height = 200;
42 config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_STENCIL | PIGLIT_GL_VISUAL_DOUBLE;
43 config.khr_no_error_support = PIGLIT_NO_ERRORS;
45 PIGLIT_GL_TEST_CONFIG_END
47 static const char *TestName = "gettextureimage-formats";
49 static const GLfloat clearColor[4] = { 0.4, 0.4, 0.4, 0.0 };
50 static GLuint texture_id;
51 static GLuint prog;
52 static bool init_by_rendering;
54 #define TEX_SIZE 128
56 #define DO_BLEND 1
59 /**
60 * Make a simple texture image where red increases from left to right,
61 * green increases from bottom to top, blue stays constant (50%) and
62 * the alpha channel is a checkerboard pattern.
63 * \return true for success, false if unsupported format
65 static bool
66 make_texture_image(GLenum intFormat, GLubyte upperRightTexel[4])
68 GLubyte tex[TEX_SIZE][TEX_SIZE][4];
69 int i, j;
70 GLuint fb, status;
72 for (i = 0; i < TEX_SIZE; i++) {
73 for (j = 0; j < TEX_SIZE; j++) {
74 tex[i][j][0] = j * 255 / TEX_SIZE;
75 tex[i][j][1] = i * 255 / TEX_SIZE;
76 tex[i][j][2] = 128;
77 if (((i >> 4) ^ (j >> 4)) & 1)
78 tex[i][j][3] = 255; /* opaque */
79 else
80 tex[i][j][3] = 125; /* transparent */
84 memcpy(upperRightTexel, tex[TEX_SIZE-1][TEX_SIZE-1], 4);
86 if (init_by_rendering) {
87 /* Initialize the mipmap levels. */
88 for (i = TEX_SIZE, j = 0; i; i >>= 1, j++) {
89 glTexImage2D(GL_TEXTURE_2D, j, intFormat, i, i, 0,
90 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
93 /* Initialize the texture with glDrawPixels. */
94 glGenFramebuffers(1, &fb);
95 glBindFramebuffer(GL_FRAMEBUFFER, fb);
96 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
97 GL_TEXTURE_2D, texture_id, 0);
98 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
99 if (status != GL_FRAMEBUFFER_COMPLETE) {
100 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, piglit_winsys_fbo);
101 glDeleteFramebuffers(1, &fb);
102 return false;
105 glViewport(0, 0, TEX_SIZE, TEX_SIZE);
107 glWindowPos2iARB(0, 0);
108 glDrawPixels(TEX_SIZE, TEX_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, tex);
109 glGenerateTextureMipmap(texture_id);
111 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, piglit_winsys_fbo);
112 glDeleteFramebuffers(1, &fb);
113 glViewport(0, 0, piglit_width, piglit_height);
114 } else {
115 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
116 glTexImage2D(GL_TEXTURE_2D, 0, intFormat, TEX_SIZE, TEX_SIZE, 0,
117 intFormat == GL_STENCIL_INDEX8 ? GL_STENCIL_INDEX : GL_RGBA, GL_UNSIGNED_BYTE, tex);
120 return glGetError() == GL_NO_ERROR;
123 static GLfloat
124 ubyte_to_float(GLubyte b, GLint bits)
126 if (bits <= 8) {
127 GLint b2 = b >> (8 - bits);
128 GLint max = 255 >> (8 - bits);
129 return b2 / (float) max;
130 } else {
131 return b / 255.0;
136 static GLfloat
137 bits_to_tolerance(GLint bits, bool compressed)
139 GLfloat t;
141 if (bits == 0) {
142 return 0.25;
143 } else if (bits == 1) {
144 return 0.5;
145 } else if (bits > 8) {
146 /* The original texture was specified as GLubyte and we
147 * assume that the window/surface is 8-bits/channel.
149 t = 4.0 / 255;
150 } else {
151 t = 4.0 / (1 << (bits - 1));
154 if (compressed) {
155 /* Use a fudge factor. The queries for GL_TEXTURE_RED/
156 * GREEN/BLUE/ALPHA_SIZE don't return well-defined values for
157 * compressed formats so using them is unreliable. This is
158 * pretty loose, but good enough to catch some Mesa bugs during
159 * development.
161 t = 0.3;
163 return t;
167 static void
168 compute_expected_color(const struct format_desc *fmt,
169 const GLubyte upperRightTexel[4],
170 GLfloat expected[4], GLfloat tolerance[4])
172 GLfloat texel[4];
173 GLint compressed;
174 int bits[4];
176 bits[0] = bits[1] = bits[2] = bits[3] = 0;
178 /* Handle special cases first */
179 if (fmt->internalformat == GL_R11F_G11F_B10F_EXT) {
180 bits[0] = bits[1] = bits[2] = 8;
181 bits[3] = 0;
182 texel[0] = ubyte_to_float(upperRightTexel[0], bits[0]);
183 texel[1] = ubyte_to_float(upperRightTexel[1], bits[1]);
184 texel[2] = ubyte_to_float(upperRightTexel[2], bits[2]);
185 texel[3] = 1.0;
186 compressed = GL_FALSE;
187 } else if (fmt->internalformat == GL_STENCIL_INDEX8) {
188 bits[0] = bits[1] = bits[2] = 7;
189 bits[3] = 0;
190 texel[0] = ubyte_to_float(upperRightTexel[0], bits[0]);
191 texel[1] = ubyte_to_float(upperRightTexel[1], bits[1]);
192 texel[2] = ubyte_to_float(upperRightTexel[2], bits[2]);
193 texel[3] = 1.0;
194 compressed = GL_FALSE;
195 } else {
196 GLint r, g, b, a, l, i;
197 GLenum baseFormat = 0;
199 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r);
200 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g);
201 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b);
202 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a);
203 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_LUMINANCE_SIZE, &l);
204 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTENSITY_SIZE, &i);
205 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &compressed);
207 if (0)
208 printf("r=%d g=%d b=%d a=%d l=%d i=%d\n", r, g, b, a, l, i);
210 if (i > 0) {
211 baseFormat = GL_INTENSITY;
212 bits[0] = i;
213 bits[1] = 0;
214 bits[2] = 0;
215 bits[3] = i;
216 texel[0] = ubyte_to_float(upperRightTexel[0], bits[0]);
217 texel[1] = 0.0;
218 texel[2] = 0.0;
219 texel[3] = ubyte_to_float(upperRightTexel[0], bits[3]);
220 } else if (a > 0) {
221 if (l > 0) {
222 baseFormat = GL_LUMINANCE_ALPHA;
223 bits[0] = l;
224 bits[1] = 0;
225 bits[2] = 0;
226 bits[3] = a;
227 texel[0] = ubyte_to_float(upperRightTexel[0], bits[0]);
228 texel[1] = 0.0;
229 texel[2] = 0.0;
230 texel[3] = ubyte_to_float(upperRightTexel[3], bits[3]);
231 } else if (r > 0 && g > 0 && b > 0) {
232 baseFormat = GL_RGBA;
233 bits[0] = r;
234 bits[1] = g;
235 bits[2] = b;
236 bits[3] = a;
237 texel[0] = ubyte_to_float(upperRightTexel[0], bits[0]);
238 texel[1] = ubyte_to_float(upperRightTexel[1], bits[1]);
239 texel[2] = ubyte_to_float(upperRightTexel[2], bits[2]);
240 texel[3] = ubyte_to_float(upperRightTexel[3], bits[3]);
241 } else if (r == 0 && g == 0 && b == 0) {
242 baseFormat = GL_ALPHA;
243 bits[0] = 0;
244 bits[1] = 0;
245 bits[2] = 0;
246 bits[3] = a;
247 texel[0] = 0.0;
248 texel[1] = 0.0;
249 texel[2] = 0.0;
250 texel[3] = ubyte_to_float(upperRightTexel[3], bits[3]);
251 } else {
252 baseFormat = 0; /* ??? */
253 texel[0] = 0.0;
254 texel[1] = 0.0;
255 texel[2] = 0.0;
256 texel[3] = 0.0;
258 } else if (l > 0) {
259 baseFormat = GL_LUMINANCE;
260 bits[0] = l;
261 bits[1] = 0;
262 bits[2] = 0;
263 bits[3] = 0;
264 texel[0] = ubyte_to_float(upperRightTexel[0], bits[0]);
265 texel[1] = 0.0;
266 texel[2] = 0.0;
267 texel[3] = 1.0;
268 } else if (r > 0) {
269 if (g > 0) {
270 if (b > 0) {
271 baseFormat = GL_RGB;
272 bits[0] = r;
273 bits[1] = g;
274 bits[2] = b;
275 bits[3] = 0;
276 texel[0] = ubyte_to_float(upperRightTexel[0], bits[0]);
277 texel[1] = ubyte_to_float(upperRightTexel[1], bits[1]);
278 texel[2] = ubyte_to_float(upperRightTexel[2], bits[2]);
279 texel[3] = 1.0;
280 } else {
281 baseFormat = GL_RG;
282 bits[0] = r;
283 bits[1] = g;
284 bits[2] = 0;
285 bits[3] = 0;
286 texel[0] = ubyte_to_float(upperRightTexel[0], bits[0]);
287 texel[1] = ubyte_to_float(upperRightTexel[1], bits[1]);
288 texel[2] = 0.0;
289 texel[3] = 1.0;
291 } else {
292 baseFormat = GL_RED;
293 bits[0] = r;
294 bits[1] = 0;
295 bits[2] = 0;
296 bits[3] = 0;
297 texel[0] = ubyte_to_float(upperRightTexel[0], bits[0]);
298 texel[1] = 0.0;
299 texel[2] = 0.0;
300 texel[3] = 1.0;
302 } else {
303 assert(!"Unexpected texture component sizes");
304 texel[0] = 0.0;
305 texel[1] = 0.0;
306 texel[2] = 0.0;
307 texel[3] = 0.0;
310 (void) baseFormat; /* not used, at this time */
313 /* compute texel color blended with background color */
314 #if DO_BLEND
315 expected[0] = texel[0] * texel[3] + clearColor[0] * (1.0 - texel[3]);
316 expected[1] = texel[1] * texel[3] + clearColor[1] * (1.0 - texel[3]);
317 expected[2] = texel[2] * texel[3] + clearColor[2] * (1.0 - texel[3]);
318 expected[3] = texel[3] * texel[3] + clearColor[3] * (1.0 - texel[3]);
319 #else
320 expected[0] = texel[0];
321 expected[1] = texel[1];
322 expected[2] = texel[2];
323 expected[3] = texel[3];
324 #endif
326 assert(expected[0] == expected[0]);
328 tolerance[0] = bits_to_tolerance(bits[0], compressed);
329 tolerance[1] = bits_to_tolerance(bits[1], compressed);
330 tolerance[2] = bits_to_tolerance(bits[2], compressed);
331 tolerance[3] = bits_to_tolerance(bits[3], compressed);
335 static bool
336 colors_equal(const GLfloat expected[4], const GLfloat pix[4],
337 GLfloat tolerance[4])
339 if (fabsf(expected[0] - pix[0]) > tolerance[0] ||
340 fabsf(expected[1] - pix[1]) > tolerance[1] ||
341 fabsf(expected[2] - pix[2]) > tolerance[2] ||
342 fabsf(expected[3] - pix[3]) > tolerance[3]) {
343 return false;
345 return true;
349 static bool
350 test_format(const struct test_desc *test,
351 const struct format_desc *fmt)
353 int x, y;
354 int w = TEX_SIZE, h = TEX_SIZE;
355 GLfloat readback[TEX_SIZE][TEX_SIZE][4];
356 GLubyte upperRightTexel[4];
357 int level;
358 GLfloat expected[4], pix[4], tolerance[4];
359 bool pass = true;
361 glClear(GL_COLOR_BUFFER_BIT);
362 glClear(GL_STENCIL_BUFFER_BIT);
364 /* The RGBA_DXT1 formats seem to expose a Mesa/libtxc_dxtn bug.
365 * Just skip them for now. Testing the other compressed formats
366 * is good enough.
368 if (fmt->internalformat != GL_COMPRESSED_RGBA_S3TC_DXT1_EXT &&
369 fmt->internalformat != GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) {
370 /* init texture image */
371 if (!make_texture_image(fmt->internalformat, upperRightTexel))
372 return true; /* unsupported = OK */
374 x = 10;
375 y = 40;
377 compute_expected_color(fmt, upperRightTexel, expected, tolerance);
379 /* Draw with the texture */
380 glUseProgram(prog);
381 dsa_set_xform(prog, piglit_width, piglit_height);
382 #if DO_BLEND
383 glEnable(GL_BLEND);
384 #endif
385 piglit_draw_rect_tex(x, y, w, h, 0.0, 0.0, 1.0, 1.0);
386 glUseProgram(0);
387 glDisable(GL_BLEND);
389 x += TEX_SIZE + 20;
391 level = 0;
392 GLenum format = fmt->internalformat == GL_STENCIL_INDEX8 ? GL_STENCIL_INDEX : GL_RGBA;
393 GLenum type = fmt->internalformat == GL_STENCIL_INDEX8 ? GL_UNSIGNED_BYTE : GL_FLOAT;
394 while (w > 0) {
395 /* Get the texture image */
396 glGetTextureImage(texture_id, level, format, type,
397 sizeof(readback), readback);
399 /* Draw the texture image */
400 glWindowPos2iARB(x, y);
401 #if DO_BLEND
402 glEnable(GL_BLEND);
403 #endif
404 glDrawPixels(w, h, format, type, readback);
405 glDisable(GL_BLEND);
407 if (level <= 2) {
408 GLint rx = x + w-1;
409 GLint ry = y + h-1;
410 glReadPixels(rx, ry, 1, 1, format, type, pix);
411 if (!colors_equal(expected, pix, tolerance)) {
412 printf("%s failure: format: %s, level %d at pixel(%d, %d)\n",
413 TestName,
414 get_format_name(
415 fmt->internalformat),
416 level, rx, ry);
417 printf(" Expected (%f, %f, %f, %f)\n",
418 expected[0], expected[1], expected[2], expected[3]);
419 printf(" Found (%f, %f, %f, %f)\n",
420 pix[0], pix[1], pix[2], pix[3]);
421 printf("Tolerance (%f, %f, %f, %f)\n",
422 tolerance[0], tolerance[1], tolerance[2], tolerance[3]);
423 pass = false;
427 x += w + 20;
428 w /= 2;
429 h /= 2;
430 level++;
435 piglit_present_results();
437 return pass;
442 * Is the given set of formats supported?
443 * This checks if required extensions are present and if this piglit test
444 * can actually grok the formats.
446 static bool
447 supported_format_set(const struct test_desc *set)
449 if (!supported(set))
450 return false;
452 if (set->format == ext_texture_integer ||
453 set->format == ext_packed_depth_stencil ||
454 set->format == arb_texture_rg_int ||
455 set->format == arb_depth_texture ||
456 set->format == arb_texture_stencil8 ||
457 set->format == arb_depth_buffer_float) {
458 /* texture_integer requires a fragment shader, different
459 * glTexImage calls. Depth/stencil formats not implemented.
461 return false;
464 return true;
468 static bool
469 test_all_formats(void)
471 bool pass = true;
472 int i, j;
474 for (i = 0; i < ARRAY_SIZE(test_sets); i++) {
475 const struct test_desc *set = &test_sets[i];
476 if (supported_format_set(set)) {
477 for (j = 0; j < set->num_formats; j++) {
478 if (!test_format(set, &set->format[j])) {
479 pass = false;
485 return pass;
489 enum piglit_result
490 piglit_display(void)
492 bool pass;
494 piglit_ortho_projection(piglit_width, piglit_height, false);
496 if (piglit_automatic) {
497 pass = test_all_formats();
498 } else {
499 const struct test_desc *set = &test_sets[test_index];
500 if (supported_format_set(set)) {
501 pass = test_format(set, &set->format[format_index]);
502 } else {
503 /* unsupported format - not a failure */
504 pass = true;
505 glClear(GL_COLOR_BUFFER_BIT);
506 piglit_present_results();
510 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
513 void
514 piglit_init(int argc, char **argv)
516 int i;
518 piglit_require_extension("GL_ARB_direct_state_access");
520 fbo_formats_init(1, argv, !piglit_automatic);
521 (void) fbo_formats_display;
523 for (i = 1; i < argc; i++) {
524 if (strcmp(argv[i], "init-by-rendering") == 0) {
525 init_by_rendering = true;
526 puts("The textures will be initialized by rendering "
527 "to them using glDrawPixels.");
528 break;
532 glGenTextures(1, &texture_id);
533 glBindTexture(GL_TEXTURE_2D, texture_id);
534 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
535 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
537 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
539 glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
540 glClearStencil(clearColor[0] * 255);
542 prog = dsa_create_program(GL_TEXTURE_2D);