2 * Copyright © 2012 Marek Olšák <maraeo@gmail.com>
3 * Copyright © 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * 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, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 * @file getcompressedtextureimage.c
28 #include "piglit-util-gl.h"
29 #include "dsa-utils.h"
31 PIGLIT_GL_TEST_CONFIG_BEGIN
33 config
.window_width
= 216;
34 config
.supports_gl_compat_version
= 20;
35 config
.supports_gl_core_version
= 31;
37 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
|
38 PIGLIT_GL_VISUAL_DOUBLE
;
39 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
41 PIGLIT_GL_TEST_CONFIG_END
43 #define IMAGE_WIDTH 32
44 #define IMAGE_HEIGHT 32
45 #define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT * 4)
49 show_image(GLubyte
*data
, int num_layers
, const char *title
)
56 if (!piglit_automatic
) {
57 prog
= dsa_create_program(GL_TEXTURE_2D
);
59 dsa_set_xform(prog
, piglit_width
, piglit_height
);
61 /* Create the texture handle. */
62 glCreateTextures(GL_TEXTURE_2D
, 1, &name
);
63 glTextureStorage2D(name
, 1, GL_RGBA8
, IMAGE_WIDTH
,
65 glTextureParameteri(name
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
66 glTextureParameteri(name
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
67 glBindTextureUnit(0, name
);
69 /* Draw the layers, separated by some space */
70 glClear(GL_COLOR_BUFFER_BIT
);
71 for (i
= 0; i
< num_layers
; ++i
) {
72 int x
= (IMAGE_WIDTH
+ DISPLAY_GAP
) * (i
% 6);
73 int y
= (IMAGE_HEIGHT
+ DISPLAY_GAP
) * (i
/ 6);
74 glTextureSubImage2D(name
, 0, 0, 0,
75 IMAGE_WIDTH
, IMAGE_HEIGHT
,
76 GL_RGBA
, GL_UNSIGNED_BYTE
,
77 data
+ i
* IMAGE_SIZE
);
78 piglit_draw_rect_tex(x
, y
, IMAGE_WIDTH
, IMAGE_HEIGHT
,
83 printf("****** %s ******\n", title
);
85 piglit_present_results();
88 printf("Enter any char to continue.\n>>>>>>");
89 (void) scanf("%s", junk
);
92 glDeleteTextures(1, &name
);
94 glDeleteProgram(prog
);
99 make_layer_data(int num_layers
)
102 GLubyte
*layer_data
=
103 malloc(num_layers
* IMAGE_SIZE
* sizeof(GLubyte
));
104 GLubyte
*data
= piglit_rgbw_image_ubyte(IMAGE_WIDTH
,
107 for (z
= 0; z
< num_layers
; z
++) {
108 memcpy(layer_data
+ IMAGE_SIZE
* z
, data
, IMAGE_SIZE
);
113 /* Show the first layer of the completed layer data. */
114 show_image(layer_data
, num_layers
, "Test Data");
120 compare_layer(int layer
, int num_elements
, int tolerance
,
121 GLubyte
*data
, GLubyte
*expected
)
125 for (i
= 0; i
< num_elements
; ++i
) {
126 if (abs((int)data
[i
] - (int)expected
[i
]) > tolerance
) {
127 printf("GetCompressedTextureImage() returns incorrect"
128 " data in byte %i for layer %i\n",
130 printf(" corresponding to (%i,%i), channel %i\n",
131 (i
/ 4) / IMAGE_WIDTH
, (i
/ 4) % IMAGE_HEIGHT
,
133 printf(" expected: %i\n", expected
[i
]);
134 printf(" got: %i\n", data
[i
]);
141 static enum piglit_result
142 getTexImage(bool doPBO
, GLenum target
, GLubyte
*data
,
143 GLenum internalformat
, int tolerance
)
146 int num_layers
=1, num_faces
=1, layer_size
;
147 GLubyte
*data2
= NULL
;
155 /* Upload the data. These are all targets that can be compressed
156 * according to _mesa_target_can_be_compressed.
160 glCreateTextures(target
, 1, &name
);
161 glTextureStorage2D(name
, 1, internalformat
, IMAGE_WIDTH
,
163 glTextureSubImage2D(name
, 0, 0, 0, IMAGE_WIDTH
, IMAGE_HEIGHT
,
164 GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
165 layer_size
= IMAGE_SIZE
;
168 case GL_TEXTURE_CUBE_MAP
:
170 glCreateTextures(target
, 1, &name
);
171 if (!piglit_khr_no_error
) {
172 /* This is invalid. You must use 2D storage call for
175 glTextureStorage3D(name
, 1, internalformat
,
176 IMAGE_WIDTH
, IMAGE_HEIGHT
,
178 pass
&= piglit_check_gl_error(GL_INVALID_OPERATION
);
180 glTextureStorage2D(name
, 1, internalformat
,
181 IMAGE_WIDTH
, IMAGE_HEIGHT
);
183 glTextureSubImage3D(name
, 0, 0, 0, 0, IMAGE_WIDTH
,
184 IMAGE_HEIGHT
, num_faces
, GL_RGBA
,
185 GL_UNSIGNED_BYTE
, data
);
186 layer_size
= IMAGE_SIZE
;
189 case GL_TEXTURE_2D_ARRAY
:
190 num_layers
= 7; /* Fall through. */
191 case GL_TEXTURE_CUBE_MAP_ARRAY
:
193 glCreateTextures(target
, 1, &name
);
194 glTextureStorage3D(name
, 1, internalformat
, IMAGE_WIDTH
,
195 IMAGE_HEIGHT
, num_layers
);
196 glTextureSubImage3D(name
, 0, 0, 0, 0,
197 IMAGE_WIDTH
, IMAGE_HEIGHT
, num_layers
,
198 GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
199 layer_size
= IMAGE_SIZE
;
203 puts("Invalid texture target.");
207 /* Make sure the driver has compressed the image. */
208 glGetTextureLevelParameteriv(name
, 0, GL_TEXTURE_COMPRESSED
,
210 printf("\tIs the texture compressed? %s.\n",
211 compressed
? "yes" : "no");
213 glGetTextureLevelParameteriv(name
, 0,
214 GL_TEXTURE_COMPRESSED_IMAGE_SIZE
,
216 /* Section 8.11 (Texture Queries) of the OpenGL 4.5 Core Profile spec
219 * "For GetTextureLevelParameter* only, texture may also be a cube
220 * map texture object. In this case the query is always performed
221 * for face zero (the TEXTURE_CUBE_MAP_POSITIVE_X face), since
222 * there is no way to specify another face."
224 if (target
== GL_TEXTURE_CUBE_MAP
)
225 comp_size
*= num_faces
;
226 printf("\tThe size of the texture in bytes is %d.\n", comp_size
);
228 /* Show the uncompressed data. */
229 show_image(data
, num_layers
* num_faces
, "Data Before Compression");
232 /* Setup the PBO or data array to read into from
233 * glGetCompressedTextureImage
236 glGenBuffers(1, &packPBO
);
237 glBindBuffer(GL_PIXEL_PACK_BUFFER
, packPBO
);
238 /* Make the buffer big enough to hold uncompressed data. */
239 glBufferData(GL_PIXEL_PACK_BUFFER
, layer_size
* num_faces
*
240 num_layers
* sizeof(GLubyte
),
241 NULL
, GL_STREAM_READ
);
243 glBindBuffer(GL_PIXEL_PACK_BUFFER
, 0);
244 data2
= malloc(layer_size
* num_faces
* num_layers
*
246 memset(data2
, 123, layer_size
* num_faces
* num_layers
*
249 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
250 assert(num_layers
* num_faces
* layer_size
<= 18 * IMAGE_SIZE
);
253 /* Download the compressed texture image. */
255 glGetCompressedTextureImage(name
, 0, comp_size
, NULL
);
257 glGetCompressedTextureImage(name
, 0, comp_size
, data2
);
258 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
261 dataGet
= (GLubyte
*) glMapBufferRange(
262 GL_PIXEL_PACK_BUFFER
, 0,
268 /* Re-upload the texture in compressed form. */
271 glCompressedTextureSubImage2D(name
, 0, 0, 0,
272 IMAGE_WIDTH
, IMAGE_HEIGHT
,
273 internalformat
, comp_size
,
277 case GL_TEXTURE_CUBE_MAP
:
278 glCompressedTextureSubImage3D(name
, 0, 0, 0, 0,
279 IMAGE_WIDTH
, IMAGE_HEIGHT
,
281 internalformat
, comp_size
,
285 case GL_TEXTURE_2D_ARRAY
:
286 case GL_TEXTURE_CUBE_MAP_ARRAY
:
287 glCompressedTextureSubImage3D(name
, 0, 0, 0, 0,
288 IMAGE_WIDTH
, IMAGE_HEIGHT
,
290 internalformat
, comp_size
,
296 /* Get the uncompressed version for comparison. */
298 glUnmapBuffer(GL_PIXEL_PACK_BUFFER
);
299 glGetTextureImage(name
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
300 layer_size
* num_layers
* num_faces
* sizeof(GLubyte
),
304 glGetTextureImage(name
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
305 layer_size
* num_layers
* num_faces
* sizeof(GLubyte
),
308 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
310 dataGet
= (GLubyte
*) glMapBufferRange(
311 GL_PIXEL_PACK_BUFFER
, 0,
312 layer_size
* num_layers
*
313 num_faces
* sizeof(GLubyte
),
318 /* Examine the image after pulling it off the graphics card. */
319 show_image(dataGet
, num_layers
* num_faces
, "Data After Compression");
321 /* Do the comparison */
322 for (i
= 0; i
< num_faces
* num_layers
; i
++) {
323 pass
= compare_layer(i
, layer_size
, tolerance
, dataGet
,
324 data
+ (i
* layer_size
)) && pass
;
325 dataGet
+= layer_size
;
329 glUnmapBuffer(GL_PIXEL_PACK_BUFFER
);
330 glDeleteBuffers(1, &packPBO
);
333 glDeleteTextures(1, &name
);
336 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
339 struct target_and_mask
{
344 static struct target_and_mask targets
[] = {
346 {GL_TEXTURE_CUBE_MAP
, 1},
347 {GL_TEXTURE_2D_ARRAY
, 1},
348 {GL_TEXTURE_CUBE_MAP_ARRAY
, 1},
352 clear_target_mask(GLenum target
)
355 for (i
= 0; i
< ARRAY_SIZE(targets
); ++i
) {
356 if (targets
[i
].target
== target
) {
363 piglit_init(int argc
, char **argv
)
365 piglit_require_extension("GL_ARB_direct_state_access");
366 piglit_require_extension("GL_ARB_texture_storage");
368 if (!piglit_is_extension_supported("GL_EXT_texture_array"))
369 clear_target_mask(GL_TEXTURE_2D_ARRAY
);
370 if (!piglit_is_extension_supported("GL_ARB_texture_cube_map_array"))
371 clear_target_mask(GL_TEXTURE_CUBE_MAP_ARRAY
);
373 glClearColor(0.5, 0.5, 0.5, 1);
380 GLenum internalformat
= GL_COMPRESSED_RGBA_FXT1_3DFX
;
383 enum piglit_result subtest
;
384 enum piglit_result result
= PIGLIT_PASS
;
386 piglit_require_extension("GL_3DFX_texture_compression_FXT1");
388 data
= make_layer_data(18);
390 for (i
= 0; i
< ARRAY_SIZE(targets
); ++i
) {
391 if (!targets
[i
].mask
)
394 printf("Testing %s into PBO\n",
395 piglit_get_gl_enum_name(targets
[i
].target
));
396 subtest
= getTexImage(true, targets
[i
].target
, data
,
397 internalformat
, tolerance
);
398 piglit_report_subtest_result(subtest
, "getTexImage %s PBO",
399 piglit_get_gl_enum_name(
401 if (subtest
== PIGLIT_FAIL
)
402 result
= PIGLIT_FAIL
;
404 printf("\n"); /* Separate tests with some white space. */
406 printf("Testing %s into client array\n",
407 piglit_get_gl_enum_name(targets
[i
].target
));
408 subtest
= getTexImage(false, targets
[i
].target
, data
,
409 internalformat
, tolerance
);
410 piglit_report_subtest_result(subtest
, "getTexImage %s",
411 piglit_get_gl_enum_name(
413 if (subtest
== PIGLIT_FAIL
)
414 result
= PIGLIT_FAIL
;
416 printf("\n\n"); /* Separate targets with some white space. */
418 if (!piglit_check_gl_error(GL_NO_ERROR
))
419 result
= PIGLIT_FAIL
;
422 /* 1D targets can't be compressed in Mesa right now, but here is a
423 * trivial test for the entry point.
425 glCompressedTextureSubImage1D(250, 0, 0, 60,
426 internalformat
, 60*4*8,
429 if (!piglit_khr_no_error
) {
431 if (!piglit_check_gl_error(GL_INVALID_OPERATION
))
432 subtest
= PIGLIT_FAIL
;
434 subtest
= PIGLIT_PASS
;
435 piglit_report_subtest_result(subtest
, "Compressed Texture"
437 if (subtest
== PIGLIT_FAIL
)
438 result
= PIGLIT_FAIL
;