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
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
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;
39 config
.supports_gl_core_version
= 31;
41 config
.window_width
= 600;
42 config
.window_height
= 200;
43 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
;
44 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
46 PIGLIT_GL_TEST_CONFIG_END
48 static const char *TestName
= "gettextureimage-formats";
50 static const GLfloat clearColor
[4] = { 0.4, 0.4, 0.4, 0.0 };
51 static GLuint texture_id
;
53 static bool init_by_rendering
;
61 * Make a simple texture image where red increases from left to right,
62 * green increases from bottom to top, blue stays constant (50%) and
63 * the alpha channel is a checkerboard pattern.
64 * \return true for success, false if unsupported format
67 make_texture_image(GLenum intFormat
, GLubyte upperRightTexel
[4])
69 GLubyte tex
[TEX_SIZE
][TEX_SIZE
][4];
73 for (i
= 0; i
< TEX_SIZE
; i
++) {
74 for (j
= 0; j
< TEX_SIZE
; j
++) {
75 tex
[i
][j
][0] = j
* 255 / TEX_SIZE
;
76 tex
[i
][j
][1] = i
* 255 / TEX_SIZE
;
78 if (((i
>> 4) ^ (j
>> 4)) & 1)
79 tex
[i
][j
][3] = 255; /* opaque */
81 tex
[i
][j
][3] = 125; /* transparent */
85 memcpy(upperRightTexel
, tex
[TEX_SIZE
-1][TEX_SIZE
-1], 4);
87 if (init_by_rendering
) {
88 /* Initialize the mipmap levels. */
89 for (i
= TEX_SIZE
, j
= 0; i
; i
>>= 1, j
++) {
90 glTexImage2D(GL_TEXTURE_2D
, j
, intFormat
, i
, i
, 0,
91 GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
94 /* Initialize the texture with glDrawPixels. */
95 glGenFramebuffers(1, &fb
);
96 glBindFramebuffer(GL_FRAMEBUFFER
, fb
);
97 glFramebufferTexture2D(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
98 GL_TEXTURE_2D
, texture_id
, 0);
99 status
= glCheckFramebufferStatus(GL_FRAMEBUFFER
);
100 if (status
!= GL_FRAMEBUFFER_COMPLETE
) {
101 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, piglit_winsys_fbo
);
102 glDeleteFramebuffers(1, &fb
);
106 glViewport(0, 0, TEX_SIZE
, TEX_SIZE
);
108 glWindowPos2iARB(0, 0);
109 glDrawPixels(TEX_SIZE
, TEX_SIZE
, GL_RGBA
, GL_UNSIGNED_BYTE
, tex
);
110 glGenerateTextureMipmap(texture_id
);
112 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, piglit_winsys_fbo
);
113 glDeleteFramebuffers(1, &fb
);
114 glViewport(0, 0, piglit_width
, piglit_height
);
116 glTexParameteri(GL_TEXTURE_2D
, GL_GENERATE_MIPMAP
, GL_TRUE
);
117 glTexImage2D(GL_TEXTURE_2D
, 0, intFormat
, TEX_SIZE
, TEX_SIZE
, 0,
118 GL_RGBA
, GL_UNSIGNED_BYTE
, tex
);
121 return glGetError() == GL_NO_ERROR
;
125 ubyte_to_float(GLubyte b
, GLint bits
)
128 GLint b2
= b
>> (8 - bits
);
129 GLint max
= 255 >> (8 - bits
);
130 return b2
/ (float) max
;
138 bits_to_tolerance(GLint bits
, bool compressed
)
144 } else if (bits
== 1) {
146 } else if (bits
> 8) {
147 /* The original texture was specified as GLubyte and we
148 * assume that the window/surface is 8-bits/channel.
152 t
= 4.0 / (1 << (bits
- 1));
156 /* Use a fudge factor. The queries for GL_TEXTURE_RED/
157 * GREEN/BLUE/ALPHA_SIZE don't return well-defined values for
158 * compressed formats so using them is unreliable. This is
159 * pretty loose, but good enough to catch some Mesa bugs during
169 compute_expected_color(const struct format_desc
*fmt
,
170 const GLubyte upperRightTexel
[4],
171 GLfloat expected
[4], GLfloat tolerance
[4])
177 bits
[0] = bits
[1] = bits
[2] = bits
[3] = 0;
179 /* Handle special cases first */
180 if (fmt
->internalformat
== GL_R11F_G11F_B10F_EXT
) {
181 bits
[0] = bits
[1] = bits
[2] = 8;
183 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
184 texel
[1] = ubyte_to_float(upperRightTexel
[1], bits
[1]);
185 texel
[2] = ubyte_to_float(upperRightTexel
[2], bits
[2]);
187 compressed
= GL_FALSE
;
189 GLint r
, g
, b
, a
, l
, i
;
190 GLenum baseFormat
= 0;
192 glGetTexLevelParameteriv(GL_TEXTURE_2D
, 0, GL_TEXTURE_RED_SIZE
, &r
);
193 glGetTexLevelParameteriv(GL_TEXTURE_2D
, 0, GL_TEXTURE_GREEN_SIZE
, &g
);
194 glGetTexLevelParameteriv(GL_TEXTURE_2D
, 0, GL_TEXTURE_BLUE_SIZE
, &b
);
195 glGetTexLevelParameteriv(GL_TEXTURE_2D
, 0, GL_TEXTURE_ALPHA_SIZE
, &a
);
196 glGetTexLevelParameteriv(GL_TEXTURE_2D
, 0, GL_TEXTURE_LUMINANCE_SIZE
, &l
);
197 glGetTexLevelParameteriv(GL_TEXTURE_2D
, 0, GL_TEXTURE_INTENSITY_SIZE
, &i
);
198 glGetTexLevelParameteriv(GL_TEXTURE_2D
, 0, GL_TEXTURE_COMPRESSED
, &compressed
);
201 printf("r=%d g=%d b=%d a=%d l=%d i=%d\n", r
, g
, b
, a
, l
, i
);
204 baseFormat
= GL_INTENSITY
;
209 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
212 texel
[3] = ubyte_to_float(upperRightTexel
[0], bits
[3]);
215 baseFormat
= GL_LUMINANCE_ALPHA
;
220 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
223 texel
[3] = ubyte_to_float(upperRightTexel
[3], bits
[3]);
224 } else if (r
> 0 && g
> 0 && b
> 0) {
225 baseFormat
= GL_RGBA
;
230 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
231 texel
[1] = ubyte_to_float(upperRightTexel
[1], bits
[1]);
232 texel
[2] = ubyte_to_float(upperRightTexel
[2], bits
[2]);
233 texel
[3] = ubyte_to_float(upperRightTexel
[3], bits
[3]);
234 } else if (r
== 0 && g
== 0 && b
== 0) {
235 baseFormat
= GL_ALPHA
;
243 texel
[3] = ubyte_to_float(upperRightTexel
[3], bits
[3]);
245 baseFormat
= 0; /* ??? */
252 baseFormat
= GL_LUMINANCE
;
257 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
269 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
270 texel
[1] = ubyte_to_float(upperRightTexel
[1], bits
[1]);
271 texel
[2] = ubyte_to_float(upperRightTexel
[2], bits
[2]);
279 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
280 texel
[1] = ubyte_to_float(upperRightTexel
[1], bits
[1]);
290 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
296 assert(!"Unexpected texture component sizes");
303 (void) baseFormat
; /* not used, at this time */
306 /* compute texel color blended with background color */
308 expected
[0] = texel
[0] * texel
[3] + clearColor
[0] * (1.0 - texel
[3]);
309 expected
[1] = texel
[1] * texel
[3] + clearColor
[1] * (1.0 - texel
[3]);
310 expected
[2] = texel
[2] * texel
[3] + clearColor
[2] * (1.0 - texel
[3]);
311 expected
[3] = texel
[3] * texel
[3] + clearColor
[3] * (1.0 - texel
[3]);
313 expected
[0] = texel
[0];
314 expected
[1] = texel
[1];
315 expected
[2] = texel
[2];
316 expected
[3] = texel
[3];
319 assert(expected
[0] == expected
[0]);
321 tolerance
[0] = bits_to_tolerance(bits
[0], compressed
);
322 tolerance
[1] = bits_to_tolerance(bits
[1], compressed
);
323 tolerance
[2] = bits_to_tolerance(bits
[2], compressed
);
324 tolerance
[3] = bits_to_tolerance(bits
[3], compressed
);
329 colors_equal(const GLfloat expected
[4], const GLfloat pix
[4],
330 GLfloat tolerance
[4])
332 if (fabsf(expected
[0] - pix
[0]) > tolerance
[0] ||
333 fabsf(expected
[1] - pix
[1]) > tolerance
[1] ||
334 fabsf(expected
[2] - pix
[2]) > tolerance
[2] ||
335 fabsf(expected
[3] - pix
[3]) > tolerance
[3]) {
343 test_format(const struct test_desc
*test
,
344 const struct format_desc
*fmt
)
347 int w
= TEX_SIZE
, h
= TEX_SIZE
;
348 GLfloat readback
[TEX_SIZE
][TEX_SIZE
][4];
349 GLubyte upperRightTexel
[4];
351 GLfloat expected
[4], pix
[4], tolerance
[4];
354 glClear(GL_COLOR_BUFFER_BIT
);
356 /* The RGBA_DXT1 formats seem to expose a Mesa/libtxc_dxtn bug.
357 * Just skip them for now. Testing the other compressed formats
360 if (fmt
->internalformat
!= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
&&
361 fmt
->internalformat
!= GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
) {
362 /* init texture image */
363 if (!make_texture_image(fmt
->internalformat
, upperRightTexel
))
364 return true; /* unsupported = OK */
369 compute_expected_color(fmt
, upperRightTexel
, expected
, tolerance
);
371 /* Draw with the texture */
373 dsa_set_xform(prog
, piglit_width
, piglit_height
);
377 piglit_draw_rect_tex(x
, y
, w
, h
, 0.0, 0.0, 1.0, 1.0);
385 /* Get the texture image */
386 glGetTextureImage(texture_id
, level
, GL_RGBA
,
387 GL_FLOAT
, sizeof(readback
),
390 /* Draw the texture image */
391 glWindowPos2iARB(x
, y
);
395 glDrawPixels(w
, h
, GL_RGBA
, GL_FLOAT
, readback
);
401 glReadPixels(rx
, ry
, 1, 1, GL_RGBA
, GL_FLOAT
, pix
);
402 if (!colors_equal(expected
, pix
, tolerance
)) {
403 printf("%s failure: format: %s, level %d at pixel(%d, %d)\n",
406 fmt
->internalformat
),
408 printf(" Expected (%f, %f, %f, %f)\n",
409 expected
[0], expected
[1], expected
[2], expected
[3]);
410 printf(" Found (%f, %f, %f, %f)\n",
411 pix
[0], pix
[1], pix
[2], pix
[3]);
412 printf("Tolerance (%f, %f, %f, %f)\n",
413 tolerance
[0], tolerance
[1], tolerance
[2], tolerance
[3]);
426 piglit_present_results();
433 * Is the given set of formats supported?
434 * This checks if required extensions are present and if this piglit test
435 * can actually grok the formats.
438 supported_format_set(const struct test_desc
*set
)
443 if (set
->format
== ext_texture_integer
||
444 set
->format
== ext_packed_depth_stencil
||
445 set
->format
== arb_texture_rg_int
||
446 set
->format
== arb_depth_texture
||
447 set
->format
== arb_depth_buffer_float
) {
448 /* texture_integer requires a fragment shader, different
449 * glTexImage calls. Depth/stencil formats not implemented.
459 test_all_formats(void)
464 for (i
= 0; i
< ARRAY_SIZE(test_sets
); i
++) {
465 const struct test_desc
*set
= &test_sets
[i
];
466 if (supported_format_set(set
)) {
467 for (j
= 0; j
< set
->num_formats
; j
++) {
468 if (!test_format(set
, &set
->format
[j
])) {
484 piglit_ortho_projection(piglit_width
, piglit_height
, false);
486 if (piglit_automatic
) {
487 pass
= test_all_formats();
489 const struct test_desc
*set
= &test_sets
[test_index
];
490 if (supported_format_set(set
)) {
491 pass
= test_format(set
, &set
->format
[format_index
]);
493 /* unsupported format - not a failure */
495 glClear(GL_COLOR_BUFFER_BIT
);
496 piglit_present_results();
500 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
504 piglit_init(int argc
, char **argv
)
508 piglit_require_extension("GL_ARB_direct_state_access");
510 fbo_formats_init(1, argv
, !piglit_automatic
);
511 (void) fbo_formats_display
;
513 for (i
= 1; i
< argc
; i
++) {
514 if (strcmp(argv
[i
], "init-by-rendering") == 0) {
515 init_by_rendering
= true;
516 puts("The textures will be initialized by rendering "
517 "to them using glDrawPixels.");
522 glGenTextures(1, &texture_id
);
523 glBindTexture(GL_TEXTURE_2D
, texture_id
);
524 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
525 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
527 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
529 glClearColor(clearColor
[0], clearColor
[1], clearColor
[2], clearColor
[3]);
531 prog
= dsa_create_program(GL_TEXTURE_2D
);