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;
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
;
52 static bool init_by_rendering
;
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
66 make_texture_image(GLenum intFormat
, GLubyte upperRightTexel
[4])
68 GLubyte tex
[TEX_SIZE
][TEX_SIZE
][4];
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
;
77 if (((i
>> 4) ^ (j
>> 4)) & 1)
78 tex
[i
][j
][3] = 255; /* opaque */
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
);
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
);
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
;
124 ubyte_to_float(GLubyte b
, GLint bits
)
127 GLint b2
= b
>> (8 - bits
);
128 GLint max
= 255 >> (8 - bits
);
129 return b2
/ (float) max
;
137 bits_to_tolerance(GLint bits
, bool compressed
)
143 } else if (bits
== 1) {
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.
151 t
= 4.0 / (1 << (bits
- 1));
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
168 compute_expected_color(const struct format_desc
*fmt
,
169 const GLubyte upperRightTexel
[4],
170 GLfloat expected
[4], GLfloat tolerance
[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;
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]);
186 compressed
= GL_FALSE
;
187 } else if (fmt
->internalformat
== GL_STENCIL_INDEX8
) {
188 bits
[0] = bits
[1] = bits
[2] = 7;
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]);
194 compressed
= GL_FALSE
;
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
);
208 printf("r=%d g=%d b=%d a=%d l=%d i=%d\n", r
, g
, b
, a
, l
, i
);
211 baseFormat
= GL_INTENSITY
;
216 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
219 texel
[3] = ubyte_to_float(upperRightTexel
[0], bits
[3]);
222 baseFormat
= GL_LUMINANCE_ALPHA
;
227 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
230 texel
[3] = ubyte_to_float(upperRightTexel
[3], bits
[3]);
231 } else if (r
> 0 && g
> 0 && b
> 0) {
232 baseFormat
= GL_RGBA
;
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
;
250 texel
[3] = ubyte_to_float(upperRightTexel
[3], bits
[3]);
252 baseFormat
= 0; /* ??? */
259 baseFormat
= GL_LUMINANCE
;
264 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[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]);
286 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
287 texel
[1] = ubyte_to_float(upperRightTexel
[1], bits
[1]);
297 texel
[0] = ubyte_to_float(upperRightTexel
[0], bits
[0]);
303 assert(!"Unexpected texture component sizes");
310 (void) baseFormat
; /* not used, at this time */
313 /* compute texel color blended with background color */
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]);
320 expected
[0] = texel
[0];
321 expected
[1] = texel
[1];
322 expected
[2] = texel
[2];
323 expected
[3] = texel
[3];
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
);
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]) {
350 test_format(const struct test_desc
*test
,
351 const struct format_desc
*fmt
)
354 int w
= TEX_SIZE
, h
= TEX_SIZE
;
355 GLfloat readback
[TEX_SIZE
][TEX_SIZE
][4];
356 GLubyte upperRightTexel
[4];
358 GLfloat expected
[4], pix
[4], tolerance
[4];
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
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 */
377 compute_expected_color(fmt
, upperRightTexel
, expected
, tolerance
);
379 /* Draw with the texture */
381 dsa_set_xform(prog
, piglit_width
, piglit_height
);
385 piglit_draw_rect_tex(x
, y
, w
, h
, 0.0, 0.0, 1.0, 1.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
;
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
);
404 glDrawPixels(w
, h
, format
, type
, readback
);
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",
415 fmt
->internalformat
),
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]);
435 piglit_present_results();
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.
447 supported_format_set(const struct test_desc
*set
)
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.
469 test_all_formats(void)
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
])) {
494 piglit_ortho_projection(piglit_width
, piglit_height
, false);
496 if (piglit_automatic
) {
497 pass
= test_all_formats();
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
]);
503 /* unsupported format - not a failure */
505 glClear(GL_COLOR_BUFFER_BIT
);
506 piglit_present_results();
510 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
514 piglit_init(int argc
, char **argv
)
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.");
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
);