2 * Copyright © 2010 Intel Corporation
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
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
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 /** @file fbo-pbo-readpixels-small.c
27 * Tests that PBO blit readpixels on a 2x2 FBO works correctly. Based
28 * on a description of a failure in clutter and figuring out the associated
31 * https://bugs.freedesktop.org/show_bug.cgi?id=25921
33 * Added depth and stencil support to test the issue:
34 * https://gitlab.freedesktop.org/mesa/mesa/-/issues/3775
37 * \author Eric Anholt <eric@anholt.net>
38 * \author Yevhenii Kharchenko <yevhenii.kharchenko@globallogic.com>
42 #include "piglit-util-gl.h"
44 const struct piglit_subtest subtests
[];
45 static struct piglit_gl_test_config
*piglit_config
;
47 PIGLIT_GL_TEST_CONFIG_BEGIN
49 piglit_config
= &config
;
50 config
.subtests
= subtests
;
52 config
.supports_gl_compat_version
= 10;
54 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
|
55 PIGLIT_GL_VISUAL_RGB
|
56 PIGLIT_GL_VISUAL_DEPTH
|
57 PIGLIT_GL_VISUAL_STENCIL
;
58 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
60 PIGLIT_GL_TEST_CONFIG_END
62 typedef struct test_case
64 GLenum internal_format
;
65 GLenum texture_component
;
66 GLenum component_to_read
;
72 const struct test_case test_case_list
[] = {
79 GL_COLOR_ATTACHMENT0_EXT
87 GL_DEPTH_ATTACHMENT_EXT
95 GL_DEPTH_ATTACHMENT_EXT
98 GL_DEPTH_COMPONENT32F
,
103 GL_DEPTH_ATTACHMENT_EXT
109 GL_UNSIGNED_INT_24_8
,
111 GL_DEPTH_STENCIL_ATTACHMENT
117 GL_UNSIGNED_INT_24_8
,
119 GL_DEPTH_STENCIL_ATTACHMENT
125 GL_UNSIGNED_INT_24_8
,
126 GL_UNSIGNED_INT_24_8
,
127 GL_DEPTH_STENCIL_ATTACHMENT
130 GL_DEPTH32F_STENCIL8
,
133 GL_FLOAT_32_UNSIGNED_INT_24_8_REV
,
135 GL_DEPTH_STENCIL_ATTACHMENT
138 GL_DEPTH32F_STENCIL8
,
141 GL_FLOAT_32_UNSIGNED_INT_24_8_REV
,
143 GL_DEPTH_STENCIL_ATTACHMENT
146 GL_DEPTH32F_STENCIL8
,
149 GL_FLOAT_32_UNSIGNED_INT_24_8_REV
,
150 GL_FLOAT_32_UNSIGNED_INT_24_8_REV
,
151 GL_DEPTH_STENCIL_ATTACHMENT
155 const uint8_t STENCIL_VALUES
[4] = {1, 1, 3, 1};
156 const float DEPTH_VALUES
[4] = {0.1f
, 0.1f
, 0.3f
, 0.1f
};
159 make_fbo(GLuint
*fbo
, GLuint
*tex
, struct test_case config
)
163 glGenTextures(1, tex
);
164 glBindTexture(GL_TEXTURE_2D
, *tex
);
165 glTexImage2D(GL_TEXTURE_2D
, 0, config
.internal_format
, 2, 2, 0,
166 config
.texture_component
, config
.texture_type
, NULL
);
168 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
169 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
171 glGenFramebuffersEXT(1, fbo
);
172 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, *fbo
);
173 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
,
178 if (!piglit_check_gl_error(GL_NO_ERROR
))
179 piglit_report_result(PIGLIT_FAIL
);
181 status
= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
);
182 if (status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
183 fprintf(stderr
, "framebuffer incomplete (status = 0x%04x)\n",
191 make_pbo(GLuint
*pbo
)
193 /* Size for max pixel size of 64bit(GL_DEPTH32F_STENCIL8) */
194 const size_t bufferSize
= 2 * 2 * 8;
196 glGenBuffersARB(1, pbo
);
197 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB
, *pbo
);
198 glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB
, bufferSize
,
199 NULL
, GL_STREAM_DRAW_ARB
);
201 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
202 piglit_report_result(PIGLIT_FAIL
);
205 glPixelStorei(GL_PACK_ALIGNMENT
, 1);
209 probe_rgba(int x
, int y
, const uint8_t *expected
, const uint8_t *observed
)
211 if (expected
[0] != observed
[0] ||
212 expected
[1] != observed
[1] ||
213 expected
[2] != observed
[2] ||
214 expected
[3] != observed
[3]) {
215 printf("Probe color at (%i,%i)\n", x
, y
);
216 printf(" Expected: b = %u g = %u r = %u a = %u\n",
217 expected
[0], expected
[1], expected
[2], expected
[3]);
218 printf(" Observed: b = %u g = %u r = %u a = %u\n",
219 observed
[0], observed
[1], observed
[2], observed
[3]);
227 probe_byte(int x
, int y
, const uint8_t *expected
, const uint8_t *observed
)
229 if (*expected
!= *observed
) {
230 printf("Probe color at (%i,%i)\n", x
, y
);
231 printf(" Expected: %u\n", *expected
);
232 printf(" Observed: %u\n", *observed
);
241 probe_depth_stencil(int x
, int y
, struct test_case config
,
242 const float *expected_depth
,
243 const uint8_t *expected_stencil
,
244 const uint8_t *observed
)
246 GLboolean pass
= GL_TRUE
;
248 switch (config
.type_to_read
) {
249 case GL_UNSIGNED_INT_24_8
:
251 uint32_t depth_as_uint
= 0;
252 memcpy((uint8_t *)(&depth_as_uint
)+1, observed
+1, 3);
253 float depth
= depth_as_uint
/ (float)UINT32_MAX
;
255 pass
&= (piglit_compare_pixels(x
, y
,
261 pass
&= probe_byte(x
, y
,
262 expected_stencil
, &observed
[0]);
265 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV
:
267 float depth
= *((float*)observed
);
268 pass
&= (piglit_compare_pixels(x
, y
,
274 pass
&= probe_byte(x
, y
,
275 expected_stencil
, &observed
[4]);
285 draw_and_probe_rgba(struct test_case config
)
287 static uint8_t green
[] = {0, 255u, 0, 0};
288 static uint8_t blue
[] = {255u, 0, 0, 0};
290 GLboolean pass
= GL_TRUE
;
293 /* bottom: green. top: blue. */
294 glColor4f(0.0, 1.0, 0.0, 0.0);
295 piglit_draw_rect(0, 0, 2, 1);
296 glColor4f(0.0, 0.0, 1.0, 0.0);
297 piglit_draw_rect(0, 1, 2, 1);
299 glReadPixels(0, 0, 2, 2,
300 config
.component_to_read
, config
.type_to_read
,
301 (void *)(uintptr_t)0);
303 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY_ARB
);
305 pass
&= probe_rgba(0, 0, green
, addr
);
306 pass
&= probe_rgba(1, 0, green
, addr
+ 4);
307 pass
&= probe_rgba(0, 1, blue
, addr
+ 8);
308 pass
&= probe_rgba(1, 1, blue
, addr
+ 12);
309 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
311 /* Read with X offset. */
312 glReadPixels(1, 0, 1, 1,
313 config
.component_to_read
, config
.type_to_read
,
314 (void *)(uintptr_t)4);
316 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER
, GL_READ_ONLY_ARB
);
318 pass
&= probe_rgba(1, 0, green
, addr
+ 4);
319 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
321 /* Read with XY offset. */
322 glReadPixels(1, 1, 1, 1,
323 config
.component_to_read
, config
.type_to_read
,
324 (void *)(uintptr_t)4);
326 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER
, GL_READ_ONLY_ARB
);
328 pass
&= probe_rgba(1, 1, blue
, addr
+ 4);
329 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
335 draw_and_probe_depth(struct test_case config
)
337 const size_t element_size
= 4;
339 GLboolean pass
= GL_TRUE
;
342 /* bottom left: 0.3. other: 0.1. */
343 glDepthMask(GL_TRUE
);
345 glClear(GL_DEPTH_BUFFER_BIT
);
347 glEnable(GL_SCISSOR_TEST
);
348 glScissor(0, 1, 1, 1);
350 glClear(GL_DEPTH_BUFFER_BIT
);
351 glDisable(GL_SCISSOR_TEST
);
353 glReadPixels(0, 0, 2, 2,
354 config
.component_to_read
, config
.type_to_read
,
355 (void *)(uintptr_t)0);
357 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY_ARB
);
359 pass
&= (piglit_compare_pixels(0, 0,
362 piglit_tolerance
, 1) != 0);
363 pass
&= (piglit_compare_pixels(1, 0,
365 (float *)(addr
+ element_size
* 1),
366 piglit_tolerance
, 1) != 0);
367 pass
&= (piglit_compare_pixels(0, 1,
369 (float *)(addr
+ element_size
* 2),
370 piglit_tolerance
, 1) != 0);
371 pass
&= (piglit_compare_pixels(1, 1,
373 (float *)(addr
+ element_size
* 3),
374 piglit_tolerance
, 1) != 0);
376 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
378 /* Read with an X offset. */
379 glReadPixels(1, 0, 1, 1,
380 config
.component_to_read
, config
.type_to_read
,
381 (void *)(uintptr_t)4);
383 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER
, GL_READ_ONLY_ARB
);
385 pass
&= (piglit_compare_pixels(1, 0,
387 (float *)(addr
+ element_size
* 1),
388 piglit_tolerance
, 1) != 0);
390 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
392 /* Read with an XY offset. */
393 glReadPixels(1, 1, 1, 1,
394 config
.component_to_read
, config
.type_to_read
,
395 (void *)(uintptr_t)4);
397 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER
, GL_READ_ONLY_ARB
);
399 pass
&= (piglit_compare_pixels(1, 1,
401 (float *)(addr
+ element_size
* 1),
402 piglit_tolerance
, 1) != 0);
404 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
410 draw_and_probe_stencil(struct test_case config
)
412 const size_t element_size
= 1;
414 GLboolean pass
= GL_TRUE
;
417 /* bottom left: 3. other: 1. */
420 glClear(GL_STENCIL_BUFFER_BIT
);
422 glEnable(GL_SCISSOR_TEST
);
423 glScissor(0, 1, 1, 1);
425 glClear(GL_STENCIL_BUFFER_BIT
);
426 glDisable(GL_SCISSOR_TEST
);
428 glReadPixels(0, 0, 2, 2,
429 config
.component_to_read
, config
.type_to_read
,
430 (void *)(uintptr_t)0);
432 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY_ARB
);
434 pass
&= probe_byte(0, 0, &STENCIL_VALUES
[0], addr
);
435 pass
&= probe_byte(1, 0, &STENCIL_VALUES
[1], addr
+ element_size
* 1);
436 pass
&= probe_byte(0, 1, &STENCIL_VALUES
[2], addr
+ element_size
* 2);
437 pass
&= probe_byte(1, 1, &STENCIL_VALUES
[3], addr
+ element_size
* 3);
439 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
441 /* Read with an X offset. */
442 glReadPixels(1, 0, 1, 1,
443 config
.component_to_read
, config
.type_to_read
,
444 (void *)(uintptr_t)4);
446 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER
, GL_READ_ONLY_ARB
);
448 pass
&= probe_byte(1, 0, &STENCIL_VALUES
[1], addr
+ element_size
* 1);
450 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
452 /* Read with an XY offset. */
453 glReadPixels(1, 1, 1, 1,
454 config
.component_to_read
, config
.type_to_read
,
455 (void *)(uintptr_t)4);
457 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER
, GL_READ_ONLY_ARB
);
459 pass
&= probe_byte(1, 1, &STENCIL_VALUES
[3], addr
+ element_size
* 1);
461 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
468 draw_and_probe_depth_and_stencil(struct test_case config
)
470 const size_t element_size
= (config
.type_to_read
==
471 GL_FLOAT_32_UNSIGNED_INT_24_8_REV
) ? 8 : 4;
473 GLboolean pass
= GL_TRUE
;
476 /* bottom left: 3. other: 1. */
477 glDepthMask(GL_TRUE
);
481 glClear(GL_STENCIL_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
483 glEnable(GL_SCISSOR_TEST
);
484 glScissor(0, 1, 1, 1);
487 glClear(GL_STENCIL_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
488 glDisable(GL_SCISSOR_TEST
);
490 glReadPixels(0, 0, 2, 2,
491 config
.component_to_read
, config
.type_to_read
,
492 (void *)(uintptr_t)0);
494 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY_ARB
);
496 pass
&= probe_depth_stencil(0, 0, config
,
497 &DEPTH_VALUES
[0], &STENCIL_VALUES
[0],
499 pass
&= probe_depth_stencil(1, 0, config
,
500 &DEPTH_VALUES
[1], &STENCIL_VALUES
[1],
501 addr
+ element_size
* 1);
502 pass
&= probe_depth_stencil(0, 1, config
,
503 &DEPTH_VALUES
[2], &STENCIL_VALUES
[2],
504 addr
+ element_size
* 2);
505 pass
&= probe_depth_stencil(1, 1, config
,
506 &DEPTH_VALUES
[3], &STENCIL_VALUES
[3],
507 addr
+ element_size
* 3);
509 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
511 /* Read with an X offset. */
512 glReadPixels(1, 0, 1, 1,
513 config
.component_to_read
, config
.type_to_read
,
514 (void *)(uintptr_t)element_size
);
516 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER
, GL_READ_ONLY_ARB
);
518 pass
&= probe_depth_stencil(1, 0, config
,
519 &DEPTH_VALUES
[1], &STENCIL_VALUES
[1],
520 addr
+ element_size
* 1);
522 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
524 /* Read with an XY offset. */
525 glReadPixels(1, 1, 1, 1,
526 config
.component_to_read
, config
.type_to_read
,
527 (void *)(uintptr_t)element_size
);
529 addr
= glMapBufferARB(GL_PIXEL_PACK_BUFFER
, GL_READ_ONLY_ARB
);
531 pass
&= probe_depth_stencil(1, 1, config
,
532 &DEPTH_VALUES
[3], &STENCIL_VALUES
[3],
533 addr
+ element_size
* 3);
535 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER
);
541 run_test_case(void *data
)
543 GLboolean pass
= GL_TRUE
;
544 GLuint fbo
, tex
, pbo
;
546 const test_case_t config
= *((test_case_t
*) data
);
548 make_fbo(&fbo
, &tex
, config
);
551 glViewport(0, 0, 2, 2);
553 switch (config
.component_to_read
) {
555 pass
= draw_and_probe_rgba(config
);
557 case GL_DEPTH_COMPONENT
:
558 pass
= draw_and_probe_depth(config
);
560 case GL_STENCIL_INDEX
:
561 pass
= draw_and_probe_stencil(config
);
563 case GL_DEPTH_STENCIL
:
564 pass
= draw_and_probe_depth_and_stencil(config
);
571 glDeleteBuffersARB(1, &pbo
);
573 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, piglit_winsys_fbo
);
575 glViewport(0, 0, piglit_width
, piglit_height
);
576 piglit_ortho_projection(piglit_width
, piglit_height
, GL_FALSE
);
578 glBindTexture(GL_TEXTURE_2D
, tex
);
579 glEnable(GL_TEXTURE_2D
);
580 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
582 piglit_draw_rect_tex(0, 0, piglit_width
, piglit_height
,
584 glDisable(GL_TEXTURE_2D
);
586 glDeleteFramebuffersEXT(1, &fbo
);
587 glDeleteTextures(1, &tex
);
589 piglit_present_results();
591 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
597 enum piglit_result pass
= PIGLIT_SKIP
;
599 pass
= piglit_run_selected_subtests(piglit_config
->subtests
,
600 piglit_config
->selected_subtests
,
601 piglit_config
->num_selected_subtests
,
607 void piglit_init(int argc
, char **argv
)
609 piglit_require_extension("GL_EXT_framebuffer_object");
610 piglit_require_extension("GL_ARB_pixel_buffer_object");
612 glDisable(GL_DITHER
);
614 piglit_ortho_projection(2, 2, GL_FALSE
);
617 const struct piglit_subtest subtests
[] = {
622 (void *)(&test_case_list
[0])
625 "GL_DEPTH_COMPONENT16-GL_DEPTH_COMPONENT",
626 "GL_DEPTH_COMPONENT16-GL_DEPTH_COMPONENT",
628 (void *)(&test_case_list
[1])
631 "GL_DEPTH_COMPONENT24-GL_DEPTH_COMPONENT",
632 "GL_DEPTH_COMPONENT24-GL_DEPTH_COMPONENT",
634 (void *)(&test_case_list
[2])
637 "GL_DEPTH_COMPONENT32F-GL_DEPTH_COMPONENT",
638 "GL_DEPTH_COMPONENT32F-GL_DEPTH_COMPONENT",
640 (void *)(&test_case_list
[3])
643 "GL_DEPTH24_STENCIL8-GL_DEPTH_COMPONENT",
644 "GL_DEPTH24_STENCIL8-GL_DEPTH_COMPONENT",
646 (void *)(&test_case_list
[4])
649 "GL_DEPTH24_STENCIL8-GL_STENCIL_INDEX",
650 "GL_DEPTH24_STENCIL8-GL_STENCIL_INDEX",
652 (void *)(&test_case_list
[5])
655 "GL_DEPTH24_STENCIL8-GL_DEPTH_STENCIL",
656 "GL_DEPTH24_STENCIL8-GL_DEPTH_STENCIL",
658 (void *)(&test_case_list
[6])
661 "GL_DEPTH32F_STENCIL8-GL_DEPTH_COMPONENT",
662 "GL_DEPTH32F_STENCIL8-GL_DEPTH_COMPONENT",
664 (void *)(&test_case_list
[7])
667 "GL_DEPTH32F_STENCIL8-GL_STENCIL_INDEX",
668 "GL_DEPTH32F_STENCIL8-GL_STENCIL_INDEX",
670 (void *)(&test_case_list
[8])
673 "GL_DEPTH32F_STENCIL8-GL_DEPTH_STENCIL",
674 "GL_DEPTH32F_STENCIL8-GL_DEPTH_STENCIL",
676 (void *)(&test_case_list
[9])